1. введение
Apache Ignite-это распределенная платформа с открытым исходным кодом, ориентированная на память. Мы можем использовать его в качестве базы данных, системы кэширования или для обработки данных в памяти.
Платформа использует память в качестве слоя хранения, поэтому имеет впечатляющую производительность. Проще говоря, это одна из самых быстрых платформ автоматической обработки данных, используемых в настоящее время в производстве.
2. Установка и настройка
Для начала ознакомьтесь со страницей начало работы для получения инструкций по первоначальной настройке и установке.
Зависимости Maven для приложения, которое мы собираемся создать:
org.apache.ignite ignite-core ${ignite.version} org.apache.ignite ignite-indexing ${ignite.version}
ignite-core является единственной обязательной зависимостью для проекта . Поскольку мы также хотим взаимодействовать с SQL, ignite-indexing также находится здесь. ${ignite.version} – это последняя версия Apache Ignite.
В качестве последнего шага мы запускаем узел воспламенения:
Ignite node started OK (id=53c77dea) Topology snapshot [ver=1, servers=1, clients=0, CPUs=4, offheap=1.2GB, heap=1.0GB] Data Regions Configured: ^-- default [initSize=256.0 MiB, maxSize=1.2 GiB, persistenceEnabled=false]
Вывод консоли выше показывает, что мы готовы к работе.
3. Архитектура памяти
Платформа основана на прочной архитектуре памяти . Это позволяет хранить и обрабатывать данные как на диске, так и в памяти. Это повышает производительность за счет эффективного использования ресурсов оперативной памяти кластера.
Данные в памяти и на диске имеют одинаковое двоичное представление. Это означает отсутствие дополнительного преобразования данных при перемещении с одного слоя на другой.
Прочная архитектура памяти разбивается на блоки фиксированного размера, называемые страницами. Страницы хранятся вне кучи Java и организованы в оперативной памяти. Он имеет уникальный идентификатор: Полная страница .
Страницы взаимодействуют с памятью с помощью абстракции Page Memory .
Это помогает читать, писать страницу, а также выделять идентификатор страницы. Внутри памяти Ignite связывает страницы с Буферами памяти .
4. Страницы Памяти
Страница может иметь следующие состояния:
- Выгружено – буфер страниц не загружен в память
- Очистить – буфер страниц загружается и синхронизируется с данными на диске.
- Durty – буфер страницы содержит данные, отличные от данных на диске
- Грязный в контрольной точке – есть еще одна модификация, которая запускается до того, как первая сохранится на диске. Здесь запускается контрольная точка, и Память страниц сохраняет два буфера памяти для каждой Страницы.
Долговременная память выделяет локальный сегмент памяти, называемый Областью данных . По умолчанию он имеет емкость 20% памяти кластера. Конфигурация нескольких областей позволяет хранить полезные данные в памяти.
Максимальная емкость области-это сегмент памяти. Это физическая память или непрерывный массив байтов.
Чтобы избежать фрагментации памяти, одна страница содержит несколько записей ключ-значение . Каждая новая запись будет добавлена на самую оптимальную страницу. Если размер пары ключ-значение превышает максимальную емкость страницы, Ignite хранит данные более чем на одной странице. Та же логика применима и к обновлению данных.
Индексы SQL и кэша хранятся в структурах, известных как деревья B+. Ключи кэша упорядочены по их значениям ключей.
5. Жизненный цикл
Каждый узел Ignite работает на одном экземпляре JVM . Однако можно настроить несколько узлов Ignite, работающих в одном процессе JVM.
Давайте рассмотрим типы событий жизненного цикла:
- BEFORE_NODE_START – перед запуском узла Ignite
- AFTER_NODE_START – срабатывает сразу после запуска узла Ignite
- BEFORE_NODE_STOP – перед началом остановки узла
- AFTER_NODE_STOP – после остановки узла воспламенения
Чтобы запустить узел воспламенения по умолчанию:
Ignite ignite = Ignition.start();
Или из файла конфигурации:
Ignite ignite = Ignition.start("config/example-cache.xml");
В случае, если нам нужно больше контроля над процессом инициализации, есть другой способ с помощью интерфейса LifecycleBean :
public class CustomLifecycleBean implements LifecycleBean { @Override public void onLifecycleEvent(LifecycleEventType lifecycleEventType) throws IgniteException { if(lifecycleEventType == LifecycleEventType.AFTER_NODE_START) { // ... } } }
Здесь мы можем использовать типы событий жизненного цикла для выполнения действий до или после запуска/остановки узла.
Для этой цели мы передаем экземпляр конфигурации с пользовательским компонентом жизненного цикла в метод start:
IgniteConfiguration configuration = new IgniteConfiguration(); configuration.setLifecycleBeans(new CustomLifecycleBean()); Ignite ignite = Ignition.start(configuration);
6. Сетка Данных В Памяти
Ignite data grid-это распределенное хранилище ключей , очень знакомое для секционированных HashMap . Он масштабируется по горизонтали. Это означает, что мы добавляем больше узлов кластера, больше данных кэшируется или хранится в памяти.
Это может обеспечить значительное повышение производительности стороннего программного обеспечения, такого как NoSQL, базы данных RDMS, в качестве дополнительного уровня для кэширования.
6.1. Поддержка кэширования
API доступа к данным основан на спецификации JCache JSR 107.
В качестве примера давайте создадим кэш с помощью конфигурации шаблона:
IgniteCachecache = ignite.getOrCreateCache( "baeldingCache");
Давайте посмотрим, что здесь происходит, для получения более подробной информации. Во-первых, Ignite находит область памяти, в которой хранится кэш.
Затем страница индекса дерева B+ будет расположена на основе хэш-кода ключа. Если индекс существует, то будет расположена страница данных соответствующего ключа.
Когда индекс равен НУЛЮ, платформа создает новую запись данных с помощью данного ключа.
Далее, давайте добавим некоторые объекты Employee :
cache.put(1, new Employee(1, "John", true)); cache.put(2, new Employee(2, "Anna", false)); cache.put(3, new Employee(3, "George", true));
Опять же, долговременная память будет искать область памяти, к которой принадлежит кэш. На основе ключа кэша страница индекса будет расположена в древовидной структуре B+.
Когда страница индекса не существует, запрашивается новая страница и добавляется в дерево.
Затем страница данных присваивается странице индекса.
Чтобы прочитать сотрудника из кэша, мы просто используем значение ключа:
Employee employee = cache.get(1);
6.2. Поддержка потоковой передачи
Потоковая передача данных в памяти обеспечивает альтернативный подход для приложений обработки данных на основе дисков и файловых систем. Потоковый API разбивает поток данных с высокой нагрузкой на несколько этапов и направляет их для обработки .
Мы можем изменить наш пример и передать данные из файла. Во-первых, мы определяем поток данных:
IgniteDataStreamerstreamer = ignite .dataStreamer(cache.getName());
Затем мы можем зарегистрировать преобразователь потока, чтобы отметить принятых сотрудников как занятых:
streamer.receiver(StreamTransformer.from((e, arg) -> { Employee employee = e.getValue(); employee.setEmployed(true); e.setValue(employee); return employee; }));
В качестве заключительного шага мы повторяем employees.txt строки файлов и преобразование их в объекты Java:
Path path = Paths.get(IgniteStream.class.getResource("employees.txt") .toURI()); Gson gson = new Gson(); Files.lines(path) .forEach(l -> streamer.addData( employee.getId(), gson.fromJson(l, Employee.class)));
С использованием стример.добавить Данные() поместите объекты сотрудников в поток.
7. Поддержка SQL
Платформа предоставляет ориентированную на память, отказоустойчивую базу данных SQL.
Мы можем подключиться либо с помощью чистого SQL API, либо с помощью JDBC. Синтаксис SQL здесь-ANSI-99, поэтому поддерживаются все стандартные функции агрегирования в запросах, операциях языка DML, DDL.
7.1. JDBC
Чтобы стать более практичным, давайте создадим таблицу сотрудников и добавим в нее некоторые данные.
Для этой цели мы регистрируем драйвер JDBC и открываем соединение в качестве следующего шага:
Class.forName("org.apache.ignite.IgniteJdbcThinDriver"); Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1/");
С помощью стандартной команды DDL мы заполняем таблицу Employee :
sql.executeUpdate("CREATE TABLE Employee (" + " id LONG PRIMARY KEY, name VARCHAR, isEmployed tinyint(1)) " + " WITH \"template=replicated\"");
После ключевого слова WITH мы можем установить шаблон конфигурации кэша. Здесь мы используем REPLICATED . По умолчанию режим шаблона СЕКЦИОНИРОВАН . Чтобы указать количество копий данных, мы также можем указать здесь параметр BACKUP , который по умолчанию равен 0.
Затем давайте сложим некоторые данные с помощью инструкции INSERT DML:
PreparedStatement sql = conn.prepareStatement( "INSERT INTO Employee (id, name, isEmployed) VALUES (?, ?, ?)"); sql.setLong(1, 1); sql.setString(2, "James"); sql.setBoolean(3, true); sql.executeUpdate(); // add the rest
После этого мы выбираем записи:
ResultSet rs = sql.executeQuery("SELECT e.name, e.isEmployed " + " FROM Employee e " + " WHERE e.isEmployed = TRUE ")
7.2. Запрос объектов
Также можно выполнить запрос по объектам Java, хранящимся в кэше . Ignite обрабатывает объект Java как отдельную запись SQL:
IgniteCachecache = ignite.cache("baeldungCache"); SqlFieldsQuery sql = new SqlFieldsQuery( "select name from Employee where isEmployed = 'true'"); QueryCursor > cursor = cache.query(sql); for (List> row : cursor) { // do something with the row }
8. Резюме
В этом уроке мы быстро ознакомились с проектом Apache Ignite. В этом руководстве освещаются преимущества платформы по сравнению с другими аналогичными продуктами, такими как повышение производительности, долговечность, легкие API.
В результате мы узнали, как использовать язык SQL и Java API для хранения, извлечения и потоковой передачи данных внутри сетки сохранения или в памяти.
Как обычно, полный код этой статьи доступен на GitHub .