はじめに
Cassandra Day Tokyo
今年、2023年6月1日に、Cassandra Dayが日本でも開催されます。
Cassandra Dayは、昨年、ベルリン、ロンドン、アムステルダム、ハノイ、ジャカルタ、ヒューストン、サンタクララ、シアトル、シンガポールでも開催されました。
今回の東京での開催に向けて、Apache Cassandraに関する記事を発表していきます。
Apache Cassandraについて
Apache Cassandraとは、一言でいうなら、オープンソースの分散データベース管理システムです。
他の分散データベース管理システム同様、複数の汎用サーバーを用いて、ひとつのデータベースを構築します(開発などの目的のため、一つのサーバーのみで構成することも可能です)。
ここでは、詳しい説明は割愛し、興味のある方へのご紹介の役割は、公式サイトやWikipediaに譲ります。
Cassandra リアクティブ スタイル プログラミング
本稿の内容は、以下のドキュメントを元にしています。
Cassandra リアクティブ スタイル プログラミングの紹介と基本的な使い方については、本稿執筆者による以下の記事を参照ください。
高度なトピック
バックプレッシャー
リアクティブ プログラミングの重要な機能の 1 つに、バックプレッシャーがあります。
残念ながら、Cassandra ネイティブ プロトコルは、ネットワークを介したクライアントとサーバー間のバックプレッシャー情報の交換を適切にサポートしていません。
バージョン 3.10 以降、Cassandra はクライアントを(暗黙的に)抑制します。
一方で、リアクティブ プログラミングのコンテクストでのバックプレッシャーのメカニズムはありません。
ただし、Cassandra からのデータの読み取りにおいて、このことはほとんどのアプリケーションで問題になることはないと言えるでしょう。
実際、読み取りシナリオでは、Cassandra はプロデューサーとして機能し、ドライバーはコンシューマーです。このようなセットアップでは、ダウンストリームのサブスクライバーがスループットに対応できない場合、ドライバーはサーバーからページを要求するレートを徐々に調整します。そのことによって、サーバーのスループットが調整され、サブスクライバーのスループットに一致されます。
唯一の注意点は、サブスクライバーが非常に遅い場合、クエリ タイムアウトをトリガーする可能性があることです(クライアント側 はDriverTimeoutException
、サーバー側 ReadTimeoutException
)。
Cassandra に書き込む場合、クライアントとサーバー間のバックプレッシャー通信の欠如がより問題になります。
実際、書き込みシナリオでは、ドライバーはプロデューサーとして機能し、Cassandra はコンシューマーです。このようなセットアップでは、アップストリーム プロデューサーが生成するデータが多すぎる場合、ドライバーはやみくもに書き込みステートメントをできるだけ早くサーバーに送信し、最終的にクラスターが過負荷になるか、クラッシュすることさえあります。これは通常、WriteTimeoutException
、または OverloadedException
といったエラーで表面化します。
書き込みが集中するシナリオでは、書き込みステートメントが実行される同時実行数を制限することを強くお勧めします。これを実現する簡単な方法は、flatMap
メソッドを使用することです。ほとんどのリアクティブ ライブラリでは、flatMap
メソッドは、同時実行数を制御するパラメータを受け取る形式になっています。
次の例では、ReactorライブラリのflatMap
で、 concurrency
パラメーター(二つ目の引数)を利用して、最大同時実行数 10 でステートメントのフローを実行します。
Flux<Statement<?>> stmts = ...;
stmts.flatMap(session::executeReactive, 10).blockLast();
上記の例では、flatMap
は同時に最大 10 並列で、ReactiveResultSet
のインスタンスにサブスクライブします。実行中の同時要求数は、10 個に制限します。
通常、データの書き込みが速すぎるのを防ぐには、これで十分です。
より高度な実装では、フローの実行をレート制限またはスロットリングできる場合があります。たとえば、Reactor は、アップストリーム パブリッシャーのスループットをレート制限するメソッド delayElements
を提供します。詳細については、ライブラリのドキュメントを参照してください。
最後の手段として、たとえばドライバーの組み込みの要求スロットリングメカニズムを使用して、ドライバー レベルで同時実行を制限することも考えられます。ただし、これは通常、リアクティブ アプリケーションでは必要ありません。いくつかの例については、開発者ガイドの「Managing concurrency in asynchronous query execution(非同期クエリ実行での同時実行の管理)」を参照してください。