12 марта 2018 г., спустя 4 месяца после прошлой версии, вышел Apache Ignite 2.4. Этот релиз примечателен целым рядом нововведений: поддержка Java 9, множественные оптимизации и улучшения SQL, поддержка платформой нейронных сетей, новый подход к построению топологии при работе с диском и многое другое.

Apache Ignite Database and Caching Platform — это платформа для распределенного хранения данных (оптимизированная под активное использование RAM), а также для распределенных вычислений в близком к реальному времени.

Ignite применяется там, где нужно очень быстро обрабатывать большие потоки данных, которые не по зубам централизованным системам.

Примеры использования: быстрый распределенный кеш; слой, агрегирующий данные из разрозненных сервисов (например, для Customer 360 View); основное горизонтально масштабируемое хранилище (NoSQL или SQL) оперативных данных; платформа для вычислений и т.д.

Далее рассмотрим основные новшества Ignite 2.4.

Baseline Topology


Если вы использовали Apache Ignite вместе с его собственным дисковым хранилищем, вам, вероятно, приходилось сталкиваться:

  • с необходимостью явно активировать кластер после старта минимального требуемого количества узлов;
  • с агрессивной ребалансировкой при смене топологии, которая может быть очень болезненной из-за активного дискового ввода-вывода.

Baseline Topology решает эти проблемы, фиксируя набор узлов, которые содержат дисковые данные, и оказывают влияние на активацию кластера, поведение при изменении топологии и ребалансировку.

Baseline Topology — это настолько важное изменение в Ignite, что в ближайшее время мы опубликуем отдельную статью, посвященную этой функции.

Тонкие клиенты


Теперь можно создавать тонкие клиенты на базе собственного бинарного протокола.

Ранее клиенты для .NET и C++ поднимали внутри себя полноценную JVM с Ignite для коммуникации с кластером. Это обеспечивало легкий и дешевый доступ к обширной функциональности платформы, но клиенты получались тяжеловесными.

Новые тонкие клиенты самостоятельны и не нуждаются в использовании JVM. Это значительно уменьшает потребление ресурсов и повышает производительность, а сообществу теперь намного легче и дешевле строить новые клиенты для самых разных языков, например, Python.

В версии 2.4 появился тонкий клиент для .NET.

var cfg = new IgniteClientConfiguration
{
    Host = "127.0.0.1"
};

using (IIgniteClient igniteClient = Ignition.StartClient(cfg))
{
    ICacheClient<int, Organization> cache = igniteClient.GetCache<int, Organization>(CacheName);

    Organization org = new Organization(
        "GridGain",
        new Address("г. Санкт-Петербург, ул. Марата, д. 69–71, корпус В", 191119),
        new Email("rusales@gridgain.com"),
        OrganizationType.Private,
        DateTime.Now
    );

    // Положить запись в кеш.
    cache.Put(1, org);

    // Получить запись в десериализованном приведенном к нужному типу формате.
    Organization orgFromCache = cache.Get(1);
}

Оптимизация загрузки данных


В Apache Ignite 2.4 добавлены инструменты для оптимизации начальной загрузки и загрузки больших объемов данных.

Теперь можно временно выключать WAL (Write Ahead Log) для отдельных таблиц в Runtime. Это позволит загружать данные с минимальным влиянием дискового ввода-вывода, что положительно скажется на пропускной способности.

После включения WAL будет немедленно сделан checkpoint на диск по текущим данным из RAM, чтобы обеспечить сохранность данных.

Отключить WAL можно посредством SQL:

-- Выключение WAL для таблицы (и нижележащего кеша).
ALTER TABLE my_table NOLOGGING;

-- Включение, аналогично, для отдельных таблицы и кеша.
ALTER TABLE my_table LOGGING;

или посредством API:

ignite.cluster().isWalEnabled(cacheName); // Проверка, включен ли WAL.
ignite.cluster().enableWal(cacheName); // Включение WAL.
ignite.cluster().disableWal(cacheName); // Выключение WAL.

Java 9


В Ignite 2.4 к уже имеющейся поддержке Java 8 добавляется Java 9.

Расширение поддержки .NET


Часто приходилось слышать вопрос: «когда Ignite для .NET начнет поддерживать .NET Core?». Рад сообщить, что, начиная с версии 2.4, Ignite.NET получает поддержку .NET Core. Более того, появляется и поддержка Mono.

Благодаря этому можно строить кросс-платформенные приложения на .NET, расширяя сферу применения Ignite мирами Linux и Mac.

В отдельной статье мы подробнее расскажем о нововведениях, касающихся .NET — тонком клиенте и поддержке .NET Core и Mono.

Многочисленные оптимизации и улучшения SQL


В Ignite 2.4 было сделано множество изменений для ускорения работы SQL. Сюда входят: многопоточное создание индексов, оптимизации десериализации объектов и поиска по первичному ключу, поддержка SQL batching на стороне кластера и многое другое.

На поприще DDL можно задавать DEFAULT-значения для колонок в создаваемых через CREATE TABLE таблицах, указывать настройки встраивания значений в деревья индексов и выполнять DROP COLUMN.

Пример создания индекса с новыми атрибутами:

// INLINE_SIZE — максимальный размер в байтах для встраивания в деревья индекса;
// PARALLEL — количество потоков индексации.
CREATE INDEX fast_city_idx ON sales (country, city) INLINE_SIZE 60 PARALLEL 8;

Нейронные сети и другие улучшения Machine Learning


В версии 2.4 появились нейронные сети на Apache Ignite.

Их ключевое преимущество — высокая производительность обучения и исполнения моделей. За счет распределенного обучения нейронных сетей и колокации вычислительных компонентов с данными на узлах кластера отпадает необходимость в ETL и долгой передаче данных во внешние системы, забивающей сеть.

// Подготовка тестовых данных.
int samplesCnt = 100000;

// Тестовые данные будут функцией sin^2 на промежутке [0; pi/2].
IgniteSupplier<Double> pointsGen = () -> (Math.random() + 1) / 2 * (Math.PI / 2);
IgniteDoubleFunction<Double> f = x -> Math.sin(x) * Math.sin(x);

IgniteCache<Integer, LabeledVector<Vector, Vector>> cache = LabeledVectorsCache.createNew(ignite);
String cacheName = cache.getName();

// Загрузка данных посредством IgniteDataStreamer.
try (IgniteDataStreamer<Integer, LabeledVector<Vector, Vector>> streamer =
                 ignite.dataStreamer(cacheName)) {
	streamer.perNodeBufferSize(10000);

	for (int i = 0; i < samplesCnt; i++) {
    double x = pointsGen.get();
    double y = f.apply(x);
    streamer.addData(i, new LabeledVector<>(new DenseLocalOnHeapVector(new double[] {x}), new DenseLocalOnHeapVector(new double[] {y})));
	}
}

// Инициализация тренера.
MLPGroupUpdateTrainer<RPropParameterUpdate> trainer = MLPGroupUpdateTrainer.getDefault(ignite).
	withSyncPeriod(3).
  withTolerance(0.0001).
  withMaxGlobalSteps(100).
  withUpdateStrategy(UpdateStrategies.RProp());

// Создание ввода для тренера.
MLPArchitecture conf = new MLPArchitecture(1).
	withAddedLayer(10, true, Activators.SIGMOID).
	withAddedLayer(1, true, Activators.SIGMOID);

MLPGroupUpdateTrainerCacheInput trainerInput = new MLPGroupUpdateTrainerCacheInput(conf,
	new RandomInitializer(new Random()), 6, cache, 1000);

// Тренировка и сверка результатов.
MultilayerPerceptron mlp = trainer.train(trainerInput);

int testCnt = 1000;

Matrix test = new DenseLocalOnHeapMatrix(1, testCnt);

for (int i = 0; i < testCnt; i++)
	test.setColumn(i, new double[] {pointsGen.get()});

Matrix predicted = mlp.apply(test);
Matrix actual = test.copy().map(f);

Vector predicted = mlp.apply(test).getRow(0);
Vector actual = test.copy().map(f).getRow(0);

// Показать предсказанные и фактические значения.
Tracer.showAscii(predicted);
Tracer.showAscii(actual);

System.out.println("MSE: " + (predicted.minus(actual).kNorm(2) / predicted.size()));

Прочее


Помимо перечисленных изменений в релиз также вошли:

Комментарии (5)


  1. Hixon10
    16.03.2018 22:30

    Добрый вечер.

    А какие пользовательские сценарии вы видите в выключении WAL-а? Особенно, если выключается это добро с помощью DDL-запроса (а не Java API), что, наверное, предполагает, что включение/выключение Лога будет выполняться при развёртывании приложения.


    1. dspavlov
      19.03.2018 13:31

      Добрый день, да, верно, один из основных сценариев — это изначальная загрузка данных при переходе на Apache Ignite. Если загрузка завершится из-за ошибки оборудования, ее можно начать снова.


  1. devozerov
    19.03.2018 11:48

    Выключать можно и с помощью Java API. Главный сценарий — быстрая загрузка данных.


  1. schernolyas
    19.03.2018 13:32

    Доброе время суток!
    Когда уж SQL станет транзакционным? Вроде как был план допилить эту функциональность в релизе 2.4. Когда теперь ждать?

    Спасибо!


  1. devozerov
    19.03.2018 13:40

    Транзакционный SQL сейчас в стадии активной разработки [1]. Озвучить сроки выхода мы пока не готовы.
    [1] issues.apache.org/jira/browse/IGNITE-4191