推測的クエリー実行
推測的クエリーは、1番目のノードが応答またはエラーを返す前に、別のノードに対する2番目のクエリーの実行を先制的に開始するのに使用します。
推測的クエリーは、1番目のノードが応答またはエラーを返す前に、別のノードに対する2番目のクエリーの実行を先制的に開始するのに使用します。ノードの応答が遅くなることがあります。そのノードに送信されたクエリーは、レイテンシーが増加します。
この状態を緩和するために、推測的実行を使用して、1番目のノードが応答またはエラーを返す前に、別のノードに対する2番目のクエリーの実行を先制的に開始します。2番目のノードの応答が早い場合、その応答はクライアントに返され、1番目の実行はキャンセルされます。1番目の実行がキャンセルされた場合、ドライバーはこの応答を無視しますが、要求とサーバーの対話は継続します。
1番目のノードは、2番目の実行コールが開始した直後に応答することがあります。この場合、2番目の推測的実行はキャンセルされます。推測的実行を使用するアプリケーションでは、ノードの応答が早い方のデータがクライアントに返されます。
構成
推測的実行は、DSEドライバーではデフォルトで無効になります。推測的実行を有効にしたり、構成したりするための方法については、ドライバー特有のリンクを参照してください。
C/C++ | C# | Java | Node.js | PHP(サポートされていません) | Python | Ruby(サポートされていません) |
調整とプラクティスの詳細
推測的実行の目標は、アプリケーションの全体的なレイテンシーを改善することです。ただし、推測的実行が多すぎると、クラスター上の負荷が増します。異常なノードに対するクエリーの送信を回避するのに推測的実行を使用している場合、正常なノードがリソース制限に達することはほとんどありません。ドライバーには、構成可能な遅延しきい値が用意されており、ここに推測的実行が送信されます。お手元のアプリケーションに見合う適切なしきい値を特定するために、正常なプラットフォーム状態(すべてのノードが立ち上がっており、通常の負荷がかかっている状態)を基準に従って評価して、応答レイテンシーをモニタリングします。これらの結果に基づいて、推測的実行しきい値として高パーセンタイル(p99.9)のレイテンシーを使用します。
もしくは、低レイテンシーが最優先され、クラスターが増大したスループットを処理可能な場合、しきい値を0に設定することで、推測的実行が常に効率的に行われます。
推測的実行では、大半のドライバーが、推測的実行の頻度を確認するのに使用することができる、メトリクスを用います。
クエリーべき等性
クエリーが、べき等でない場合、ドライバーがクエリーに対して推測的実行をスケジューリングすることは絶対にありません。これは、1つのコーディネーターだけがミューテーションを適用するという保証がないためです。
リトライ
推測的実行をオンにしても、ドライバーのリトライ動作は変わりません。並列実行毎に、リトライが独自にトリガーされます。同じクエリーのすべての実行が、常に同じクエリー・プランを共有するという以外の影響はないため、各ノードは1つの実行だけで使用されます。
ストリームIDの枯渇
推測的実行の影響の1つは、数多くの要求がキャンセルされることで、その結果、ストリームIDの枯渇と呼ばれる現象を招く可能性があります。TCP接続ごとに、同時に複数の要求を処理することが可能で、ストリームIDと呼ばれる一意の番号で認識されます。「接続をプールする」を参照してください。要求がキャンセルされると、その要求のストリームIDをすぐに使用することはできません。これは、その要求に対する応答が、要求を実行した時点で追ってサーバーから返される可能性があるためです。このような現象に頻繁に遭遇する場合、時間の経過と共に利用可能なストリームIDの数が減ります。利用可能なストリームIDが所定のしきい値を下回ると、その接続は閉じられ、新しい接続が作成されます。要求が頻繁にキャンセルされる場合、接続は高い割合でリサイクルされます。
実際には、接続上のストリームIDがすべて枯渇するような事態にはなりません。接続ごとに、32768ストリームIDを参照することができます。大半のドライバー実行は、接続あたり送信できる要求は1000までにデフォルトで構成されています。
大半のドライバーには、ノードに対する進行中の要求の数を確認するためのメトリクスが用意されています。ドライバーの中には、孤立ストリームIDの数を確認するためのメトリクスが用意されているものもあります。こうしたメトリクスをモニタリングして、ストリームID枯渇が発生していないことを確認します。
ストリームID枯渇が発生している場合、クラスターにさらに容量を追加するか、リソースの制限を回避するためにノードのシステム設定を調整することです。リソース制限を回避するようにノードのシステム設定を調整するのが、代表的なソリューションです。
要求の順序指定
順序指定が問題になるのは、サーバー側のタイムスタンプを使用している場合に限られます。DataStaxドライバーの最新バージョンは、C++、PHP、ならびにRubyドライバーを除き、クライアント側のタイムスタンプを使用しています。サーバー側のタイムスタンプを使用するように、ドライバーが明示的に構成されていない限り、このセクションは関係ありません。詳細は、「クエリー・タイムスタンプ」を参照してください。
たとえば、次のクエリーは推測的実行とサーバー側のタイムスタンプが有効になっている状態で実行されます。
INSERT INTO my_table (k, v) VALUES (1, 1);
1番目の実行が遅い場合、2番目の実行がトリガーされます。最終的に、1番目の実行が完了されるため、2回目の実行はキャンセルされます。ただし、実行のキャンセルはドライバーが、サーバーの応答に対する待機を停止することだけを意味します。要求は引き続き、アクティブにしておくことが可能です。
ドライバーが実行をキャンセルした後、2番目の要求が引き続きアクティブな間は、以下のクエリーが実行され、完了します。
DELETE from my_table where k = 1;
INSERT
クエリーの2番目の要求は最終的にターゲット・ノードに到達し、INSERT
を適用します。ドライバーが2番目の要求をキャンセルしたにもかかわらず、正常に削除された行が戻ります。