Apache Igniteのガイド
1前書き
Apache Igniteは、オープンソースのメモリ中心の分散プラットフォームです。データベース、キャッシングシステム、またはインメモリデータ処理に使用できます。
このプラットフォームはメモリをストレージレイヤとして使用するため、優れたパフォーマンスを発揮します。簡単に言えば、これは現在プロダクションで使用されている最速のアトミックデータ処理プラットフォームの1つです。
** 2インストールと設定
**
はじめに、初期設定とインストールの説明についてはhttps://apacheignite.readme.io/docs/getting-started[getting started page]をチェックしてください。
これから作成するアプリケーションの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
もここにあります。
https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.apache.ignite%22%20AND%20a%3A%22ignite-core%22
}]は、Apache Igniteの最新バージョンです。
最後のステップとして、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]----
上記のコンソール出力は、準備が整ったことを示しています。
[[architecture]]
=== 3.メモリアーキテクチャ
** このプラットフォームは、耐久メモリアーキテクチャ** に基づいています。これにより、データをディスクとメモリの両方に保存して処理することができます。クラスタのRAMリソースを効果的に使用することでパフォーマンスが向上します。
メモリ内とディスク上のデータは同じバイナリ表現です。
これは、あるレイヤから別のレイヤに移動している間にデータを追加変換しないことを意味します。
耐久性のあるメモリアーキテクチャは、ページと呼ばれる固定サイズのブロックに分割されます。
ページはJavaヒープの外部に格納され、RAMにまとめられています。 __FullPageId__という一意の識別子があります。
ページは__PageMemory__抽象化を使用してメモリと対話します。
また、ページの読み取り、書き込み、およびページIDの割り当てに役立ちます。 ** メモリ内で、Igniteはページを__Memory Buffers__ ** に関連付けます。
[[pages]]
=== ** 4メモリーページ**
ページは次のような状態になります。
** Unloaded - メモリにページバッファがロードされていません
** クリア - ページバッファはロードされ、データと同期します。
ディスク
** Durty - ページバッファはそれとは異なるデータを保持します
ディスク内
** チェックポイントが汚れています。
最初のものはディスクに固執します。ここでチェックポイントが始まり、__PageMemory__は各ページに2つのメモリバッファを保持します。
** 永続メモリは__Data Region __と呼ばれるメモリセグメントをローカルに割り当てます。** デフォルトでは、クラスタメモリの20%の容量があります。複数領域構成では、使用可能なデータをメモリに保存できます。
領域の最大容量はメモリセグメントです。これは物理メモリまたは連続バイト配列です。
** メモリの断片化を避けるために、単一のページに複数のKey-Valueエントリがあります** 。すべての新しいエントリは最も最適なページに追加されます。キーと値のペアのサイズがページの最大容量を超えると、Igniteはデータを複数のページに保存します。同じ論理がデータの更新にも当てはまります。
SQLインデックスとキャッシュインデックスは、Bツリーと呼ばれる構造に格納されます。キャッシュキーはそれらのキー値によって順序付けられます。
=== ** 5ライフサイクル**
** 各Igniteノードは単一のJVMインスタンス上で実行されます** 。ただし、単一のJVMプロセスで複数のIgniteノードを実行するように設定することは可能です。
ライフサイクルイベントの種類を見てみましょう。
** __BEFORE__NODE__START__ - Igniteノードの起動前
** __AFTER__NODE__START__ - Igniteノードの起動直後に起動します。
** __BEFORE__NODE__STOP__ - ノード停止を開始する前
** __AFTER__NODE__STOP__ - Igniteノードが停止した後
デフォルトのIgniteノードを起動するには
[source,java,gutter:,true]
Ignite ignite = Ignition.start();
または設定ファイルから: [source,java,gutter:,true]
Ignite ignite = Ignition.start(“config/example-cache.xml”);
初期化プロセスをもっと細かく制御する必要がある場合は、__LifecycleBean__インターフェースを使用して別の方法があります。 [source,java,gutter:,true]
public class CustomLifecycleBean implements LifecycleBean {
@Override public void onLifecycleEvent(LifecycleEventType lifecycleEventType) throws IgniteException {
if(lifecycleEventType == LifecycleEventType.AFTER__NODE__START) { //... } } }
ここでは、ライフサイクルイベントタイプを使用して、ノードの開始/停止の前後にアクションを実行できます。 そのために、__CustomLifecycleBean__を持つ構成インスタンスをstartメソッドに渡します。 [source,java,gutter:,true]
IgniteConfiguration configuration = new IgniteConfiguration();
configuration.setLifecycleBeans(new CustomLifecycleBean());
Ignite ignite = Ignition.start(configuration);
[[data__grid]] === 6.インメモリデータグリッド ** Igniteデータグリッドは分散型のKey-Valueストレージ** であり、パーティション化された__HashMap__に非常によく知られています。水平方向に拡大縮小されます。これは、追加するクラスタノードが増え、より多くのデータがキャッシュされるか、メモリに格納されることを意味します。 NoSql、RDMSデータベースなどのサードパーティ製ソフトウェアのパフォーマンスを大幅に向上させることができます。これにより、キャッシングのための追加レイヤとして機能します。 [[caching__support]] ==== ** 6.1. キャッシングサポート** ** データアクセスAPIはJCache JSR 107仕様に基づいています。 例として、テンプレート設定を使ってキャッシュを作成しましょう: [source,java,gutter:,true]
IgniteCache<Employee, Integer> cache = ignite.getOrCreateCache(
“baeldingCache”);
詳細については、ここで何が起こっているのかを見てみましょう。まず、Igniteはキャッシュが格納されているメモリ領域を見つけます。 その後、B +ツリーインデックスPageはキーハッシュコードに基づいて検索されます。 インデックスが存在する場合、対応するキーのデータページが配置されます。 インデックスがNULLの場合、プラットフォームは指定されたキーを使用して新しいデータエントリを作成します。 次に、__Employee__オブジェクトをいくつか追加しましょう。 [source,java,gutter:,true]
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ツリー構造に配置されます。 ** インデックスページが存在しない場合は、新しいページが要求されてツリーに追加されます。** 次に、データページがインデックスページに割り当てられています。 従業員をキャッシュから読み取るには、キー値を使用します。 [source,java,gutter:,true]
Employee employee = cache.get(1);
[[streaming__support]] ==== ** 6.2. ストリーミングサポート** インメモリデータストリーミングは、ディスクおよびファイルシステムベースのデータ処理アプリケーションに代替アプローチを提供します。 ** ストリーミングAPIは、高負荷のデータフローを複数のステージに分割し、それらを処理のためにルーティングします** 。 例を修正してファイルからデータをストリーミングすることができます。まず、データストリーマを定義します。 [source,java,gutter:,true]
IgniteDataStreamer<Integer, Employee> streamer = ignite
.dataStreamer(cache.getName());
次に、ストリームトランスフォーマーを登録して、受け取った従業員を雇用されているものとしてマークします。 [source,java,gutter:,true]
streamer.receiver(StreamTransformer.frome, arg) → { Employee employee = e.getValue(); employee.setEmployed(true); e.setValue(employee); return employee; };
最後のステップとして、__employees.txt__ファイル行を繰り返し処理し、それらをJavaオブジェクトに変換します。 [source,java,gutter:,true]
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()__を使用して、従業員オブジェクトをストリームに入れます。 [[sql__support]] === ** 7. SQLサポート** このプラットフォームは、メモリ中心の、フォールトトレラントなSQLデータベースを提供します。 純粋なSQL APIまたはJDBCのどちらでも接続できます。ここでのSQL構文はANSI-99なので、クエリ内のすべての標準集計関数、DML、DDL言語操作がサポートされています。 ==== ** 7.1. JDBC ** より実用的にするために、従業員のテーブルを作成し、それにデータを追加しましょう。 そのために、次のステップとしてJDBCドライバを登録して接続を開きます。 [source,java,gutter:,true]
Class.forName(“org.apache.ignite.IgniteJdbcThinDriver”);
Connection conn = DriverManager.getConnection(“jdbc:ignite:thin://127.0.0.1/”);
標準のDDLコマンドを使用して、__Employee__テーブルにデータを入力します。 [source,java,gutter:,true]
sql.executeUpdate(“CREATE TABLE Employee (”
” id LONG PRIMARY KEY, name VARCHAR, isEmployed tinyint(1)) ”
” WITH \”template=replicated\””);
WITHキーワードの後に、キャッシュ設定テンプレートを設定できます。 ここでは__REPLICATED__を使います。 ** デフォルトでは、テンプレートモードは__PARTITIONED__ ** です。 ** データのコピー数を指定するために、ここで__BACKUPS__ ** パラメータを指定することもできます。これはデフォルトで0です。 それでは、INSERT DMLステートメントを使用してデータを追加しましょう。 [source,java,gutter:,true]
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();
その後、レコードを選択します。 [source,java,gutter:,true]
ResultSet rs
= sql.executeQuery(“SELECT e.name, e.isEmployed ”
+ ” FROM Employee e ”
+ ” WHERE e.isEmployed = TRUE “)
==== ** 7.2. オブジェクトを照会する** ** キャッシュに格納されているJavaオブジェクトに対してクエリを実行することも可能です。 IgniteはJavaオブジェクトを別のSQLレコードとして扱います。 [source,java,gutter:,true]
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概要** このチュートリアルでは、Apache Igniteプロジェクトについて簡単に説明しました。このガイドでは、パフォーマンスの向上、耐久性、軽量APIなど、他の類似製品に対するプラットフォームの利点について説明します。 その結果、SQLまたはJava APIを使用して永続グリッドまたはインメモリグリッド内でデータを格納、取得、ストリーミングする方法を学習しました。 いつものように、この記事の完全なコードはhttps://github.com/eugenp/tutorials/tree/master/libraries-data/[over on GitHub]から入手できます。