21

ZooKeeper のlock のレシピを読んでいて、混乱しました。分散ロックのこのレシピは、「2 つのクライアントが同じロックを保持しているとは思わない時間内のスナップショット」を保証できないようです。しかし、ZooKeeper は非常に広く採用されているため、参考文献にそのような間違いがある場合は、誰かがずっと前に指摘しているはずですが、何を誤解したのでしょうか?

分散ロックのレシピを引用する:

ロック

グローバルに同期された完全に分散されたロック。つまり、任意のスナップショットで、2 つのクライアントが同じロックを保持しているとは見なしません。これらは ZooKeeper を使用して実装できます。プライオリティ キューと同様に、最初にロック ノードを定義します。

  1. " locknode /guid-lock- " というパス名を指定して create( ) を呼び出し、シーケンス フラグとエフェメラル フラグを設定します。
  2. ウォッチ フラグを設定せずにロック ノードで getChildren( ) を呼び出します (これは、群れ効果を回避するために重要です)。
  3. 手順 1 で作成されたパス名に最小のシーケンス番号サフィックスが付いている場合、クライアントはロックされ、クライアントはプロトコルを終了します。
  4. クライアントは、次に小さいシーケンス番号を持つロック ディレクトリ内のパスに監視フラグを設定して exists( ) を呼び出します。
  5. exists( ) が false を返す場合は、ステップ 2 に進みます。それ以外の場合は、ステップ 2 に進む前に、前のステップからのパス名の通知を待ちます。

次のケースを検討してください。

  • Client1 は、ZooKeeper ノード "locknode/guid-lock-0" を使用して (手順 3 で) ロックを正常に取得しました。
  • Client2 はノード「locknode/guid-lock-1」を作成しましたが、ロックの取得に失敗し、現在「locknode/guid-lock-0」を監視しています。
  • その後、何らかの理由 (たとえば、ネットワークの輻輳) で、Client1 は時間どおりに ZooKeeper クラスターにハートビート メッセージを送信できませんでしたが、Client1 はまだロックを保持していると誤って想定して、別の場所で作業を続けています。
  • ただし、ZooKeeper は Client1 のセッションがタイムアウトしたと判断し、

    1. 「locknode/guid-lock-0」を削除し、
    2. Client2 に通知を送信します (または、最初に通知を送信しますか?)、
    3. しかし、「セッション タイムアウト」通知を Client1 に時間内に送信できません (たとえば、ネットワークの輻輳のため)。
  • Client2 は通知を受け取り、ステップ 2 に進み、自分で作成した唯一のノード「locknode/guid-lock-1」を取得します。したがって、Client2 はロックを保持していると想定します。
  • しかし同時に、Client1 はロックを保持していると想定します。

これは有効なシナリオですか?

4

3 に答える 3

15

あなたが説明するシナリオが発生する可能性があります。クライアント 1 はロックされていると思っていますが、実際にはセッションがタイムアウトしており、クライアント 2 がロックを取得しています。

ZooKeeper クライアント ライブラリは、接続が切断されたことをクライアント 1 に通知します (ただし、クライアントは、クライアントがサーバーに接続するまでセッションの有効期限が切れたことを認識しません)。そのため、クライアントはコードを記述して、ロックが失われたと想定できます。彼があまりにも長い間切断されていた場合。しかし、ロックを使用するスレッドは、ロックがまだ有効であることを定期的に確認する必要があり、これは本質的に際どいものです。

于 2013-01-11T14:32:20.240 に答える
0

...しかし、Zookeeper は client1 のセッションがタイムアウトしたと判断し、その後...

Zookeeper のドキュメントから:

  • ノードを削除しても、各ノードは 1 つのクライアントによってのみ監視されるため、1 つのクライアントのみが起動します。このようにして、群れ効果を回避します。
  • ポーリングやタイムアウトはありません。

したがって、あなたが説明した問題は発生しないと思います。ロックを作成するクライアントに何かが発生した場合、ロックがハングするリスクがあると思われますが、説明したシナリオは発生しないはずです。

于 2013-01-11T12:04:10.840 に答える
0

packt book から - Zookeeper Essentials

If there was a partial failure in the creation of znode due to connection loss, it's possible that the client won't be able to correctly determine whether it successfully created the child znode. To resolve such a situation, the client can store its session ID in the znode data field or even as a part of the znode name itself. As a client retains the same session ID after a reconnect, it can easily determine whether the child znode was created by it by looking at the session ID.

于 2021-12-17T12:37:43.293 に答える