ApacheIgniteのガイド
1. 序章
Apache Igniteは、オープンソースのメモリ中心の分散プラットフォームです。 データベース、キャッシングシステム、またはメモリ内のデータ処理に使用できます。
プラットフォームはストレージレイヤーとしてメモリを使用するため、優れたパフォーマンスレートを実現します。 簡単に言えば、これは現在本番環境で使用されている最速のアトミックデータ処理プラットフォームの1つです。
2. インストールとセットアップ
まず、スタートページで初期設定とインストール手順を確認してください。
構築するアプリケーションのMaven依存関係:
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-core</artifactId>
<version>${ignite.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-indexing</artifactId>
<version>${ignite.version}</version>
</dependency>
ignite-coreは、プロジェクトの唯一の必須の依存関係です。 SQLとも対話したいので、ignite-indexingもここにあります。 ${ignite.version}はApacheIgniteの最新バージョンです。
最後のステップとして、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. メモリアーキテクチャ
プラットフォームは耐久性のあるメモリアーキテクチャに基づいています。 これにより、データをディスクとメモリの両方に保存して処理できます。 クラスタのRAMリソースを有効に活用することでパフォーマンスを向上させます。
メモリ内とディスク上のデータは同じバイナリ表現を持っています。 これは、あるレイヤーから別のレイヤーに移動するときに、データの追加の変換がないことを意味します。
耐久性のあるメモリアーキテクチャは、ページと呼ばれる固定サイズのブロックに分割されます。 ページはJavaヒープの外部に保存され、RAMに編成されます。 一意の識別子があります:FullPageId。
ページは、PageMemory抽象化を使用してメモリと対話します。
ページの読み取り、書き込み、およびページIDの割り当てに役立ちます。 メモリ内で、Igniteはページをメモリバッファに関連付けます。
4. メモリページ
ページは次の状態を持つことができます。
- アンロード–メモリにページバッファがロードされていません
- クリア–ページバッファがロードされ、ディスク上のデータと同期されます
- 耐久性–ページバッファはディスク内のデータとは異なるデータを保持します
- チェックポイントが汚れている–最初の変更がディスクに保持される前に別の変更が開始されます。 ここでチェックポイントが開始され、PageMemoryはページごとに2つのメモリバッファを保持します。
耐久性のあるメモリは、データ領域と呼ばれるメモリセグメントをローカルに割り当てます。デフォルトでは、クラスタメモリの容量は20% ofです。 複数リージョン構成により、使用可能なデータをメモリに保持できます。
領域の最大容量はメモリセグメントです。 これは、物理メモリまたは連続バイト配列です。
メモリの断片化を回避するために、1つのページに複数のキー値エントリが保持されます。 すべての新しいエントリは、最適なページに追加されます。 キーと値のペアのサイズがページの最大容量を超える場合、Igniteはデータを複数のページに保存します。 同じロジックがデータの更新にも適用されます。
SQLおよびキャッシュインデックスは、B+ツリーと呼ばれる構造に格納されます。 キャッシュキーは、キー値の順に並べられています。
5. ライフサイクル
各Igniteノードは単一のJVMインスタンスで実行されます。 ただし、単一のJVMプロセスで複数のIgniteノードを実行するように構成することは可能です。
ライフサイクルイベントの種類を見てみましょう。
- BEFORE_NODE_START –Igniteノードの起動前
- AFTER_NODE_START –Igniteノードの開始直後に発生します
- BEFORE_NODE_STOP –ノード停止を開始する前
- AFTER_NODE_STOP –Igniteノードが停止した後
デフォルトのIgniteノードを開始するには:
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) {
// ...
}
}
}
ここでは、ライフサイクルイベントタイプを使用して、ノードの開始/停止の前後にアクションを実行できます。
そのために、CustomLifecycleBeanを含む構成インスタンスをstartメソッドに渡します。
IgniteConfiguration configuration = new IgniteConfiguration();
configuration.setLifecycleBeans(new CustomLifecycleBean());
Ignite ignite = Ignition.start(configuration);
6. インメモリデータグリッド
Igniteデータグリッドは分散型Key-Valueストレージであり、パーティション化されたHashMapに非常に馴染みがあります。 水平方向に拡大縮小されます。 これは、追加するクラスターノードが増えることを意味し、より多くのデータがメモリにキャッシュまたは保存されます。
キャッシュの追加レイヤーとして、NoSqlやRDMSデータベースなどのサードパーティソフトウェアのパフォーマンスを大幅に向上させることができます。
6.1. キャッシングサポート
データアクセスAPIは、JCacheJSR107仕様に基づいています。
例として、テンプレート構成を使用してキャッシュを作成しましょう。
IgniteCache<Employee, Integer> cache = ignite.getOrCreateCache(
"baeldingCache");
詳細については、ここで何が起こっているかを見てみましょう。 まず、Igniteは、キャッシュが保存されているメモリ領域を見つけます。
次に、キーハッシュコードに基づいてB+ツリーインデックスページが検索されます。 インデックスが存在する場合は、対応するキーのデータページが検索されます。
インデックスがNULLの場合、プラットフォームは指定されたキーを使用して新しいデータエントリを作成します。
次に、いくつかの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は、高負荷のデータフローを複数のステージに分割し、処理のためにルーティングします。
例を変更して、ファイルからデータをストリーミングできます。 まず、データストリーマーを定義します。
IgniteDataStreamer<Integer, Employee> streamer = 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)));
streamer.addData()を使用して、従業員オブジェクトをストリームに配置します。
7. SQLサポート
このプラットフォームは、メモリ中心のフォールトトレラントSQLデータベースを提供します。
純粋なSQLAPIまたは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を使用します。 デフォルトでは、テンプレートモードはPARTITIONEDです。 データのコピー数を指定するために、ここでBACKUPSパラメーターを指定することもできます。これはデフォルトでは0です。
次に、INSERTDMLステートメントを使用していくつかのデータを追加しましょう。
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レコードとして扱います。
IgniteCache<Integer, Employee> cache = ignite.cache("baeldungCache");
SqlFieldsQuery sql = new SqlFieldsQuery(
"select name from Employee where isEmployed = 'true'");
QueryCursor<List<?>> cursor = cache.query(sql);
for (List<?> row : cursor) {
// do something with the row
}
8. 概要
このチュートリアルでは、ApacheIgniteプロジェクトについて簡単に説明しました。 このガイドでは、パフォーマンスの向上、耐久性、軽量APIなど、他の類似製品に対するプラットフォームの利点を強調しています。
その結果、SQL言語とJavaAPIを使用して、永続グリッドまたはメモリ内グリッド内のデータを保存、取得、ストリーミングする方法を学びました。
いつものように、この記事の完全なコードは、GitHubでから入手できます。