2フェーズコミットは、最後の1秒間の失敗をどのように防止しますか?
-
05-07-2019 - |
質問
私は、分散トランザクション全体で2フェーズコミットがどのように機能するかを研究しています。フェーズの最後の部分で、トランザクションコーディネーターが各ノードにコミットの準備ができているかどうかを尋ねることは理解しています。全員が同意したら、先に進んでコミットするように指示します。
次の失敗の原因は何ですか?
- すべてのノードが応答します コミットする準備ができました
- トランザクション コーディネーターは「先に進む」ように伝えます コミット"しかし、ノードの1つ これを受け取る前にクラッシュする メッセージ
- 他のすべてのノードは正常にコミットしますが、分散トランザクションは破損しています
- クラッシュしたノードが戻ってきたとき、そのトランザクションはロールバックされていることを理解しています(コミットメッセージを受け取ったことがないため)
各ノードは、分散トランザクションについて何も知らない通常のデータベースを実行していると仮定しています。私は何を見逃したのですか?
解決 2
全員の回答の要約:
-
分散トランザクションで通常のデータベースを使用することはできません。データベースは、トランザクションコーディネーターを明示的にサポートする必要があります。
-
一部のノードがすでにコミットされているため、ノードはロールバックするように指示されません。クラッシュしたノードが戻ってくると、トランザクションコーディネーターはコミットを終了するように指示します。
他のヒント
いいえ、元のポスターのシナリオではノードの一部がすでにコミットされているため、ロールバックするように指示されていません。クラッシュしたノードが利用可能になると、トランザクションコーディネーターは再度コミットするように指示します。
ノードが「準備」で肯定的に応答したためフェーズでは、クラッシュから戻った場合でも「コミット」できる必要があります。
いいえ。ポイント4は間違っています。各ノードは安定したストレージにトランザクションをコミットまたはロールバックできたことを記録するため、クラッシュが発生してもコマンドどおりに実行できます。クラッシュしたノードが復旧すると、コミット前の状態のトランザクションがあることを認識し、関連するロックまたはその他のコントロールを復元し、コーディネーターサイトに連絡してトランザクションのステータスを収集しようとする必要があります。
問題は、クラッシュしたノードが復帰しない場合にのみ発生します(他のすべてがトランザクションが正常であると判断するか、クラッシュしたノードが復帰したときに発生します)。
2フェーズコミットは絶対確実ではなく、99%の時間のケースで機能するように設計されています。
"プロトコルは、各ノードに先書きログのある安定したストレージがあり、ノードが永久にクラッシュしないこと、先読みログのデータがクラッシュしても失われたり破損したりしないこと、および2つのノードは互いに通信できます。"
2フェーズコミットで問題を攻撃する方法は多数あります。それらのほとんどすべてが、Paxosの3フェーズコミットアルゴリズムのバリアントとして作成されます。 GoogleでPaxosに基づくChubbyロックサービスを設計したMike Burrowsは、「Paxosと不正なもの」の2種類の分散コミットアルゴリズムがあると述べました。 -私が見た講義で。
クラッシュしたノードが再起動したときにできることの1つは、「このトランザクションについて聞いたことがありません。コミットされるべきですか?」コーディネーターに、投票が何であったかを伝えます。
これはより一般的な問題の例であることに注意してください。クラッシュしたノードは、回復する前に多くのトランザクションを失う可能性があります。そのため、リカバリ時に、自身を使用可能にする前にコーディネーターまたは別のレプリカのいずれかと通信することが非常に重要です。ノード自体がクラッシュしたかどうかを判断できない場合、事態はより複雑になりますが、扱いやすくなります。
データベースの読み取りに定足数システムを使用すると、不整合はマスクされます(データベース自体に通知されます)。