アトミックバッチは、単一のバッチ内のすべてのステートメントが実行されるか、実行されないことをどのように保証できますか?
内部でバッチがどのように機能するかを理解するには、バッチ実行の個々の段階を確認すると便利です。
クライアント
バッチは CQL またはmodern CassandraクライアントAPIを使用してサポートされます。いずれの場合も、バッチの一部として実行するステートメントのリストを指定できます。 、すべてのステートメントに使用される整合性レベルとオプションのタイムスタンプ。INSERT、DELETE、およびUPDATEステートメントをバッチ実行できます。タイムスタンプを指定しないことを選択した場合、現在の時刻が自動的に使用され、バッチに関連付けられます。 。
バッチを正常に実行できなかった場合、クライアントは2つの例外を処理する必要があります。
writeType
値(BATCH_LOG
またはBATCH
のいずれか)を読み取ることで確認できます。バッチログ段階で失敗した書き込みは 1回再試行 JavaドライバーのDefaultRetryPolicy
によって自動的に行われます。バッチログの作成は、バッチが確実に実行されるようにするために重要です。コーディネーターが操作の途中で失敗した場合に備えて、常に完了してください。理由については、以下をお読みください。
コーディネーター
クライアントによって送信されるすべてのバッチは、他の書き込み操作と同様に、コーディネーターによって実行されます。通常の書き込み操作との違いは、Cassandraは、現在実行されているすべての保留中のバッチを含む専用ログ(バッチログと呼ばれる)も使用することです。このログは、ローカルシステムのキースペースに保存されます。各バッチの実行は、コーディネーター以外の2つのノードで完全なバッチを含むログエントリを作成することから始まります。コーディネーターが他のノードでバッチログを作成できるようになると、バッチ内の実際のステートメント。
バッチ内の各ステートメントは、バッチ全体のCLとタイムスタンプを使用してレプリカに書き込まれます。それ以外に、この時点で発生する書き込みについて特別なことは何もありません。書き込みは、ヒントを与えられたり、WriteTimeoutExceptionをスローしたりすることもあります。これは、クライアントが処理できます(上記を参照)。
バッチが実行された後、作成されたすべてのバッチログを安全に削除できます。そのため、コーディネーターは、正常に実行されると、以前にバッチログを受信したノードにバッチログ削除メッセージを送信します。これはバックグラウンドで発生し、失敗した場合は気付かれません。
バッチ実行中にコーディネーターが行うことをまとめましょう。
バッチログレプリカノード
上記のように、バッチログは、バッチ実行の前に、他の2つのノード間で複製されます(クラスターサイズで許可されている場合)。アイデアは、バッチ内のすべてのステートメントを終了する前にコーディネーターがダウンした場合に備えて、これらのノードのいずれかが保留中のバッチを取得できるようにすることです。
考えを少し複雑にしているのは、それらのノードがコーディネーターがもう生きていないことに気付かないという事実です。バッチログノードがバッチ実行の現在のステータスで更新される唯一のポイントは、コーディネーターがバッチが正常に実行されたことを示す削除メッセージを発行しているときです。このようなメッセージが届かない場合、batchlogノードは、何らかの理由でバッチが実行されていないと見なし、ログからバッチを再生します。
バッチログの再生は、潜在的に毎分行われます。これは、ノードがローカルバッチログに、-おそらくkilled-コーディネーターによって削除されていない保留中のバッチがあるかどうかを確認する間隔です。コーディネーターにバッチログの作成から実際の実行までの時間を与えるために、固定の猶予期間が使用されます(write_request_timeout_in_ms * 2
、デフォルトは4秒)。バッチログが4秒経過してもまだ存在する場合は、再生されます。
Cassandraでの書き込み操作と同様に、タイムアウトが発生する可能性があります。この場合、ノードはタイムアウトした操作のヒントの書き込みにフォールバックします。タイムアウトしたレプリカが再び起動すると、ヒントから書き込みを再開できます。この動作は、hinted_handoff_enabled
が有効になっているかどうかに関係なく影響を受けていないようです。ヒントに関連付けられたTTL値もあります。これにより、長期間後にヒントが破棄されます(関連するCFの最小のGCGraceSeconds
)。
ここで、2つのノードでバッチを同時に再生することは潜在的に危険ではないかどうか疑問に思うかもしれません。これは、2つのノードでバッチログを複製した場合に発生する可能性があります。ここで覚えておくべき重要なことは、サポートされる操作(更新と削除)の種類が限られていることと、バッチに関連付けられているタイムスタンプが固定されていることにより、各バッチの実行がべき等になることです。ノードとコーディネーターの両方がバッチの実行を同時に再試行しても、競合は発生しません。
アトミシティ保証
「アトミックバッチ」のアトミック性の側面に戻り、アトミック( source )の正確な意味を確認しましょう。
"(データベースでは、バッチのいずれかの部分が成功した場合、すべてが成功するという意味で「アトミック」を意味することに注意してください。他の保証は含まれていません。特に、分離はありません。他のクライアントは最初のクライアントを読み取ることができます。他の行が進行中に、バッチから行を更新しました。」
したがって、ある意味で「オールオアナッシング」の保証が得られます。ほとんどの場合、コーディネーターはバッチ内のすべてのステートメントをクラスターに書き込むだけです。ただし、書き込みタイムアウトの場合は、writeType
値を読み取って、タイムアウトが発生した時点を確認する必要があります。これらの保証が引き続き適用されることを確認するには、バッチがバッチログに書き込まれている必要があります。また、この時点で、他のクライアントもバッチから部分的に実行された結果を読み取る場合があります。
質問に戻ると、Cassandraは、バッチ内のステートメントがすべて実行されるか、まったく実行されないことをどのように保証できますか?アトミックバッチは、基本的に、レプリケーションの成功とべき等ステートメントに依存します。100%ではありません。理論的には保証されたソリューションがあるかもしれません シナリオ それでも不整合が発生しますが、Cassandraの多くのユースケースでは、知っている場合は非常に便利なツールです使い方。
バッチドキュメント( doc ):
Cassandra 1.2以降では、バッチはデフォルトでアトミックです。Cassandraバッチ操作のコンテキストでは、アトミックとは、バッチのいずれかが成功した場合、すべてアトミック性を実現するために、Cassandraは最初にシリアル化されたバッチをblobデータとして消費するbatchlogシステムテーブルに書き込みます。バッチ内の行が正常に書き込まれ、永続化されたとき(またはヒント)バッチログデータが削除されます。アトミック性にはパフォーマンスのペナルティがあります。このペナルティを発生させたくない場合は、UNLOGGEDオプションを使用してCassandraがバッチログシステムに書き込むのを防ぎます。ログに記録されていないバッチを開始します
カサンドラバッチ:-
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/batch_r.html
上記の回答に追加するには:-Cassandra 2.0を使用すると、バッチステートメント+ LWTを記述できます。ただし、すべてのDMLが同じパーティションに存在する必要があるという制限があります。