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()));
Прочее
Помимо перечисленных изменений в релиз также вошли:
- начальная поддержка Spark DataFrames;
- оптимизация потребления памяти при работе с диском;
- множественные оптимизации дискового хранилища (например, при работе с WAL);
- проброска новых значение мониторинга в JMX (например, для мониторинга будет доступна долгожданная занятая кешами память, расширенная информация по топологии);
- RPM-пакеты с Ignite (репозиторий).
Автор: Артем Шитов