クロックバウンド待機

クラスタノード間で値の読み書きを行う前に、ノード間の時間的不確実性をカバーするために待機することで、値をクラスタノード間で正しく順序付けることができます。

問題

値がタイムスタンプ付きで格納され、各バージョンが指定されるキーバリューストアを考えてみましょう。クライアントリクエストを処理するどのクラスタノードも、リクエスト処理ノードの現在のタイムスタンプを使用して最新バージョンを読み取ることができます。

下の図では、値 `Before Dawn` は、Greenのクロックに従って時刻2に値 `After Dawn` に更新されます。AliceとBobの両方が `title` の最新値を読み取ろうとしています。AliceのリクエストはクラスタノードAmberによって処理されますが、BobのリクエストはクラスタノードBlueによって処理されます。Amberのクロックは1で遅れているため、Aliceが最新値を読み取ると、値 `Before Dawn` が配信されます。Blueのクロックは2であるため、Bobが最新値を読み取ると、値 `After Dawn` が返されます。

これは、外部整合性と呼ばれるものを違反しています。AliceとBobが電話をかけると、Aliceは混乱します。Bobは彼女に最新値が `After Dawn` であることを伝えますが、彼女のクラスタノードは `Before Dawn` を表示しています。

Greenのクロックが速く、書き込みがAmberのクロックに従って将来発生する場合も同様です。

システムのタイムスタンプが値を格納するためのバージョンとして使用される場合、これは問題です。なぜなら、システムのタイムスタンプは単調ではないからです。2つの異なるサーバーからのクロック値を比較することはできず、比較すべきではありません。ハイブリッドクロックバージョン付き値のバージョンとして使用される場合、値を単一サーバー上、および因果関係のある異なるサーバー上で順序付けることができます。ただし、ハイブリッドクロック(または他の種類のランポートクロック)は「半順序」のみを提供できます。これは、因果関係がなく、異なるノードの2つの異なるクライアントによって格納された値を順序付けることができないことを意味します。これは、タイムスタンプを使用してクラスタノード全体で値を読み取るときに問題が発生します。読み取り要求がクロックの遅れているクラスタノードで発生した場合、指定された値の最新バージョンを読み取ることができない可能性があります。

解決策

読み取りまたは書き込み中に、クラスタノードは、クラスタ内のすべてのノードのクロック値が値に割り当てられたタイムスタンプよりも確実に大きくなるまで待機します。

クロック間の差が非常に小さい場合、書き込み要求は大きなオーバーヘッドを追加することなく待機できます。たとえば、クラスタノード間の最大クロックオフセットが10ミリ秒であるとします。(これは、任意の時点で、クラスタ内で最も遅いクロックが最も速いクロックから最大10ミリ秒遅れていることを意味します。)他のすべてのクラスタノードのクロックが時刻*t*を超えていることを保証するために、書き込み操作を処理するクラスタノードは、値を格納する前に*t* + 10ミリ秒まで待機する必要があります。

詳細については、oreilly.comのオンライン電子書籍の第24章をご覧ください。

このパターンは、分散システムのパターンの一部です。

2023年11月23日