Локальная установка и настройка in memory базы данных Apache Ignite без использования docker

Установка
Скачиваем актуальную версию apache ignite
из mirror.linux-ia64.org/apache.
Подготовка сервера.
mkdir $HOME/ignite $HOME/ignite-data $HOME/logs; \ touch $HOME/ignite-config.xml $HOME/run.sh; \ chmod +x $HOME/run.sh; \ wget https://mirror.
linux-ia64.org/apache//ignite/2.15.0/apache-i... \ unzip apache-ignite-2.15.0-bin.zip; \ mv apache-ignite-2.15.0-bin $HOME/ignite
Пример конфигурации ignite-config.xml
(создаем в $HOME/ignite-config.xml)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <bean class="org.apache.ignite.configuration.IgniteConfiguration" id="ignite.cfg"> <property name="workDirectory" value="/home/www/ignite-data/"/> <property name="dataStorageConfiguration"> <bean class="org.apache.ignite.configuration.DataStorageConfiguration"> <property name="walSegmentSize" value="#{1024 * 1024 * 1024}"/> <!-- SSD page size --> <property name="pageSize" value="#{4 * 1024}"/> <property name="defaultDataRegionConfiguration"> <bean class="org.apache.ignite.
configuration.DataRegionConfiguration"> <property name="name" value="default_data_region"/> <property name="initialSize" value="#{1L * 1024 * 1024 * 1024}"/> <property name="maxSize" value="#{100L * 1024 * 1024 * 1024}"/> </bean> </property> <property name="dataRegionConfigurations"> <list> <bean class="org.apache.ignite.configuration.DataRegionConfiguration"> <property name="name" value="persist_data_region"/> <property name="initialSize" value="#{1L * 1024 * 1024 * 1024}"/> <property name="maxSize" value="#{100L * 1024 * 1024 * 1024}"/> <property name="pageEvictionMode" value="RANDOM_2_LRU"/> <!-- persist options --> <property name="persistenceEnabled" value="true"/> <property name="warmUpConfiguration"> <bean class="org.apache.ignite.configuration.LoadAllWarmUpConfiguration"/> </property> </bean> </list> </property> </bean> </property> </bean> <bean id="clientConnectorConfiguration" class="org.apache.ignite.configuration.ClientConnectorConfiguration"> <property name="maxOpenCursorsPerConnection" value="128"/> </bean> </beans>
Пример запуска run.sh
(нужен для systemd конфигурации)
JVM_OPTS указаны с учетом того, что запуск производится из под пользователя www
.
#!/bin/bash IGNITE_HOME=/home/www/ignite export IGNITE_HOME # MaxDirectMemorySize = walSegmentSize * 4 export JVM_OPTS="$JVM_OPTS \ -Duser.timezone=Europe/Moscow \ -Xms1g \ -Xmx4g \ -server \ -XX:MaxMetaspaceSize=128m \ -XX:MaxDirectMemorySize=1g \ -XX:+AlwaysPreTouch \ -XX:+UseG1GC \ -XX:+ScavengeBeforeFullGC \ -XX:+DisableExplicitGC \ -XX:+HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath=/home/www/logs/heapdump.txt \ -XX:+ExitOnOutOfMemoryError \ -XX:+PrintGCDetails \ -XX:+PrintGCTimeStamps \ -XX:+PrintGCDateStamps \ -XX:+UseGCLogFileRotation \ -XX:NumberOfGCLogFiles=10 \ -XX:GCLogFileSize=100M \ -Xloggc:/home/www/logs/oggc.txt \ -XX:+PrintAdaptiveSizePolicy \ -XX:+UnlockCommercialFeatures \ -XX:+FlightRecorder \ -XX:+UnlockDiagnosticVMOptions \ -XX:+DebugNonSafepoints" export DEFAULT_CONFIG="/home/www/ignite-config.xml" $IGNITE_HOME/bin/ignite.sh
Конфигурация systemd сервиса
vim /etc/systemd/system/ignite.service
[Unit] Description=Apache Ignite Service After=network.target [Service] WorkingDirectory=/home/www/ignite User=www PrivateDevices=yes ProtectSystem=full Type=simple ExecReload=/bin/kill -HUP $MAINPID KillMode=mixed KillSignal=SIGTERM TimeoutStopSec=10 ExecStart=/home/www/run.sh SyslogIdentifier=Ignite Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target Alias=ignite.service
Рекомендации из оф. документации.
sudo sysctl -w vm.swappiness=0 sudo sysctl -w vm.extra_free_kbytes=1240000 sudo sysctl -w vm.zone_reclaim_mode=0 sudo sysctl -w vm.dirty_writeback_centisecs=500 sudo sysctl -w vm.dirty_expire_centisecs=500
Запуск сервиса.
sudo systemctl enable ignite.service sudo systemctl start ignite sudo systemctl status ignite # check logs sudo journalctl -u ignite -f
В рамках тестирования сформируем ETL-процесс переливки данных из PostgreSQL в Ignite
Создание тестовой таблицы Ignite
CREATE TABLE public.test( trans_id varchar(255) not NULL PRIMARY key, amount int not null, decimal_amount decimal(19, 3) not null, client varchar(255) not null, operation_type varchar(10) not null, ex_text_field varchar not null, transaction_ts timestamp not null, transaction_dt date not null );
Создание тестовой таблицы PostgreSQL
create table wg.gendata( trans_id varchar(255) not null, amount int not null, decimal_amount decimal(19, 3) not null, client varchar(255) not null, operation_type varchar(10) not null, ex_text_field text not null, transaction_ts timestamp not null, transaction_dt date not null );
Сформируем тестовые даннные с помощью python скрипта.
def gen_test_data(): _test_data = [] for index in range(1, 1_000_000+1): data = { "trans_id": f"C{uuid4().hex.upper()}", "amount": randint(100, 200), "decimal_amount": uniform(0.00001, 25.123), "client": f"FFM{randint(115, 720)}", "operation_type": "C2C", "ex_text_field": "pyignite.exceptions", "transaction_ts": datetime.now(), "transaction_dt": datetime.now().strftime("%Y-%m-%d"), } _test_data.append(list(data.values())) return _test_data
Создадим функционал для быстрой вставки и запроса данных.
import psycopg2.extras from time import time from uuid import uuid4 from datetime import datetime from random import randint, uniform class PostgresConnect: def __init__(self): self.conn = psycopg2.connect( dbname="database_name", user="username", password="password", host="111.222.333.444", port=5432 ) self.cusror = self.conn.cursor() self.conn.autocommit = True def fast_insert(self, table_name: str, data): start = time() columns = ",".join([ "trans_id", "amount", "decimal_amount", "client", "operation_type", "ex_text_field", "transaction_ts", "transaction_dt" ]) cmd_template = f"insert into {table_name}({columns}) values %s" psycopg2.extras.execute_values( self.cusror, cmd_template, data, page_size=1000 ) finish = time() - start print(f"Вставка тестовых данных в кол-ве {len(data)} завершена за {round(finish/60, 3)} минуты") def fetch(self, limit: int): self.cusror.execute(f"select * from wg.gendata limit {limit}") data = self.cusror.fetchall() return data
Запуск генерации данных
pg = PostgresConnect() test_data = gen_test_data() pg.fast_insert("wg.gendata", test_data)
Запуск speedtest’a
import pyignite from pyignite.exceptions import SQLError session = pyignite.Client(handshake_timeout=20.0) session.connect("111.222.333.444", 10800) LIMIT = 1_000_000 def insert_(data: tuple, table_name: str): columns = ",".join([ "trans_id", "amount", "decimal_amount", "client", "operation_type", "ex_text_field", "transaction_ts", "transaction_dt" ]) cmd = f"insert into {table_name}({columns}) values (?, ?, ?, ?, ?, ?, ?, ?)" try: session.sql(cmd, query_args=data) except SQLError: pass def speedtest(data: list): session.sql("delete from public.test;") start = time() for row in data: insert_(row, "public.test") finish = time() - start print(f"Прошло времени, ss: {round(finish, 3)} // Кол-во {len(data)} // RPS: {round(len(data) / round(finish))}") result_set = pg.fetch(LIMIT) speedtest(result_set)
Заключение
Замер скорости с использованием pyignite
показал весьма скромный результат RPS = 90
В то время как аналогичный сервис написанный на JAVA
, с использованием JDBC
(ignite-core.jar) и SET STREAMING ON
показал цифры RPS от 10000 до 15000
Большое спасибо всем за внимание!
Подписывайтесь на мой телеграм-канал artydev & Co.