2013-01-11 9 views
17

動物園のrecipe for lockを読んでいるうちに、混乱しました。この分散ロックのレシピは、"2人のクライアントが同じロックを保持していると思うスナップショットはありません"という保証はできません。しかし、ZooKeeperは非常に広く採用されているので、リファレンスドキュメントにこのような間違いがあった場合、誰かがそれを先に指摘していたはずなので、私は何を誤解しましたか? the recipe for distributed locksを引用飼い葉桶のロックレシピに関する懸念

:グローバル同期している

ロック

完全分散ロック、時間内の任意のスナップショットで意味なし2つのクライアントは、彼らが同じロックを保持すると思うん。これらはZooKeeeperを使用して実装できます。優先度キューと同様に、最初にロック・ノードを定義します。

  1. コールは "locknode/GUID-ロックイン" と設定されたシーケンスと短命フラグのパス名に()を作成します。
  2. ウォッチフラグを設定せずにロックノードでgetChildren()を呼び出します(これは群れの影響を避けるために重要です)。
  3. 手順1で作成したパス名のシーケンス番号の接尾辞が最も小さい場合、クライアントはロックを持ち、クライアントはプロトコルを終了します。
  4. クライアントコールは、ロックディレクトリ内のパスにwatchフラグが設定されており、次のシーケンス番号が最も低くなります。

    :)(存在する場合はfalseを返します
  5. 、考えてみましょう以下のケースを2

ステップに行く前に、前のステップからのパス名の通知を待って、それ以外の場合は手順2に進みます。

  • Client1がZooKeeperノード「locknode/guid-lock-0」を使用してロックを取得しました(手順3)。
  • クライアント2のノード「locknode/guid-lock-1」がロックの取得に失敗し、現在「locknode/guid-lock-0」を監視しています。
  • その後、何らかの理由で(ネットワーク輻輳など)、Client1はZooKeeperクラスタにハートビートメッセージを送信できませんが、Client1はまだロックを保持していると誤って処理しています。
  • しかし、ZooKeeperのはクライアント1のセッションがタイムアウトしていると思うし、その後

    1. 削除 "locknode/guidをロック-0" も、
    2. は、クライアント2に通知を送信(または多分最初の通知を送信しますか? )、
    3. (ただし、ネットワークの輻輳のために)「セッションタイムアウト」通知をClient1に送信できません。
  • クライアント2は、「locknode /のGUIDロック-1" 、それ自体を作成した」だけのノードを取得し、ステップ2に進み、通知を取得し;従って、クライアント2は、それがロックを保持前提
  • しかしで同じ時刻に、Client1はロックを保持しているとみなします。

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

+1

_zookeeper-users_メーリングリストに関するパラレルディスカッション:http://thread.gmane.org/gmane.comp.java.hadoop.zookeeper.user/5065 – seh

答えて

15

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

ZooKeeperクライアントライブラリは、接続が切断されたことをクライアント1に通知します(ただし、クライアントはサーバーに接続するまでセッションが期限切れになっていることを知らないため)。クライアントはコードを記述し、ロックが切れてしまった場合、ロックは失われています。しかし、ロックを使用するスレッドは、ロックが有効であることを定期的にチェックする必要があります。

+0

;これは、 "不変" - **スナップショットでは2人のクライアントが同じロックを保持しているとは思っていません**。 – hulunbier

+0

が正しいこと – sbridges

+3

「いつでもスナップショットで」不変式に違反する別の些細な方法は、ロックを保持しているクライアント上で長いGC一時停止です。例:クライアントCがロックを取得し、java GCを保持している間にプロセスが60秒間フリーズします。これらの秒のうちの10秒後に、Cセッションが終了し、別のプロセスがロックを取得します。時間11は、「2人のクライアントが同じロックを保持していると思ったときのスナップショット」です。 – Marco

0

...しかし、飼育係はCLIENT1のセッションがタイムアウトしていると思うし、飼育係のドキュメントから、その後...

ことがあります。

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

だから私はあなたが説明する問題は発生しないと思います。それは、クライアントを作成する何かが発生した場合にロックを掛けるリスクがあると思うので私には見えますが、あなたが記述したシナリオは発生してはいけません。

+0

ありがとう;私はあなたのアイデアをうまく​​理解できません。 "群衆の影響を避ける" && "no polling or timeouts"は、クライアント1がロックを保持している間にクライアント2がロックを取得できないことを保証できません。さらに、一時的なノードは、セッションタイムアウト後にZKによって自動的に削除されるので、「ロックを掛ける危険性」も表示されません。 – hulunbier

+0

Client1のセッションがタイムアウトした場合、ロックは存在しなくなりますが、Client1はその時点でZookeeperからSESSION_EXPIREDまたはCONNECTION_LOSSを取得しているため、接続が失われていることがわかります。 – glenatron

+0

しかし、SESSION_EXPIREDメッセージがClient1に送信されなかった場合** **時間内に?一時的に高いパケット損失率のために、例えば(TCP接続は確立されたままです) – hulunbier

関連する問題