複数の値がいつ利用できるかを理解し、値を選択した結果を確認するために、Paox を使用して実行できるロック プロトコルを記述する必要があります。
ロックは、 の形式でロック トークン値を保持するセルですL={T,P}
。ここP
で、 はロックを保持しているプロセス、T
はプロセスがロックを取得した時刻です。クライアントが送信するロックを取得するには、現在のロック トークンであると考えられるV={Lc,Ln}
場所と、設定したい新しいロック トークンを送信します。ロックを解除するために特別なトークンを送信できます。メッセージが現在のトークンと一致する正しいことを示していない場合、新しいトークンは設定されません。このコンペア アンド スワップ (CAS) により、遅延ロック解除メッセージが誤って適用されるのを防ぎます。また、クライアントがロックを盗むことができる場合にロックをタイムアウトするように機能します。2 つのプロセスが 2 つの競合メッセージを送信し、Lc
Ln={T',P'}
Nil
Lc
{L1,L2}
{L1,L3}
成功できるのは1つだけです。プロセスは、ロック値である戻り値を検査することにより、操作が成功したかどうかを学習しますL
。{Nil,Nil}
プロセスは、開いているロックのロックを解除する「何もしない」CAS を送信することにより、ロック値を照会できます。ただし、ロックが閉じている場合は、誰がロックを所有しているかを返します。
書き込みはリーダーを通過する必要があります。ノードがリーダーではないことを認識している場合、クライアントをリーダーにリダイレクトする必要があります。ノードが誰がリーダーかわからない場合、エラーをスローし、クライアントは別のノードをランダムに選択する必要があります。ノードがリーダーであると判断した場合、ノードの大部分が新しい値を受け入れたことが確実な場合にのみ、クライアントに応答できます。これは、Paxos が過半数によって受け入れられた値がクラスターによって永続化されていることを保証するためです。ノードがリードしていた場合、受諾の過半数が聞こえず、クライアントに応答できません。他のノードから分離されている可能性があります。他のノードには、新しく選出されたリーダーがいる場合があります。これは以下にも当てはまります{Nil,Nil}
クライアントに現在のロック値を伝えるために、リーダーがまだリーダーであることを確認するために過半数の受け入れを必要とするクエリ。最終的に、ノードは、新しいリーダーが存在するかどうかを確認する必要があります。そうでない場合、過半数に受け入れられた値を取得しようとしてタイムアウトになります。次に、クライアントを新しいリーダーにリダイレクトするか、クライアントにエラーを返す必要があります。
これで、リーダーのフェイルオーバー中に複数の値を考慮することができます。クライアント Aは、3 ノード クラスタV1
のリーダー ノードに成功するはずの有効な CAS 更新を送信します。X
ノードはそれ自体とノードおよびノードにX
送信します。は独自の値を受け入れ、 からも受け入れられますが、ネットワークはメッセージを にドロップします。その後、ノードは暗くなり、しばらくメッセージの発行を停止します。死んでいるか失速している可能性がありますが、まだわかりません。それは大部分を見ていましたが、その運命を知るために別のメッセージを見るまで、今では謎のシュレディンガーの猫が死んでいるか生きているかのどちらかです. これは、Paxos がコラボレーションを使用して、次に何が起こっても一貫した正しい結果を得ることを選択した場所です。accept(N1,V1)
Y
Z
Y
Z
X
X,Y
リーダーからの応答が長すぎるため、しばらくするとノードZ
がタイムアウトします。propose(N2)
自分自身と他のノードに発行します。promise(N2,V1)
ノードY
とそれ自体から戻りpromise(N2,empty)
ます。それは過半数Y,Z
を占めており、リードすることができます。ノードのみX
が、値V1
が過半数に受け入れられたこと、およびクライアントが CAS が成功したと通知されたかどうかを認識します。しかし、それは沈黙しています。ノードZ
は保守的な選択をしなければなりません。ノードが死んでいると仮定すると、X
それは間違っている可能性があります。ノードX
は生きていて、操作が成功したことをクライアントに伝えている可能性があります。ノードは、最初の値としてZ
リードすることにより、最後のリーダーの部分的な作業を協力して完了する必要があります。V1
したがって、accept(N2,V1)
3 つのノードすべてに送信されます。現在、ノードかどうかは問題ではありませんX
死んでいるか生きているか、クライアントに操作が成功したかどうかを伝えていました。すべての場合において、ロック プロトコルに違反することはなく、クライアントは、エラー時に再試行すると、最終的にロックされていることがわかります。それは、どの提案やどのノードが作業をコミットしたかを見たり気にしたりしません。