Zookeeperが分散ロックを実装する原理

Zookeeperが分散ロックを実装する原理

[[384001]]

この記事はWeChatの公開アカウント「Rookie Flying」から転載したもので、著者はLiu Jinkunです。この記事の転載については、Cainiao Feiyafei公式アカウントまでご連絡ください。

序文

ByteDance の面接を受けたとき、次のような質問に遭遇しました。「Zookeeper を使用して分散ロックを実装するにはどうすればよいですか?」

ほとんどの面接では、Redis を使用して分散ロックを実装することについて取り上げられており、Zookeeper を使用して分散ロックを実装することは比較的一般的ではないと思います。最近、過去のインタビューの回答を整理していたので、それを説明するブログを書きました。

通常、分散ロックを実装する方法は多数ありますが、より一般的なのは redis と Zookeeper です。皆さんは、Redis の分散ロックの実装についてはすでによくご存知だと思います。今日はZookeeperを使って分散ロックを実装する方法を紹介します。

まず、Zookeeper が分散ロックを実装できるのはなぜでしょうか?これは、複数のスレッドが Zookeeper にアクセスして同じノードを作成する場合、1 つのスレッドのみが正常に実行されるという機能があるためです。

動物園の飼育係 ZNode

Zookeeper が分散ロックを実装する方法を理解する前に、まず、Zookeeper のノードに関連する知識を理解する必要があります。

Zookeeper 内のノードは、一時ノードと永続ノードの 2 つのカテゴリに分けられます。

一時ノードとは、ノードが作成された後に、ノードを作成したクライアントと Zookeeper サーバー間のセッションが失敗した場合 (たとえば、接続が切断された場合)、ノードが削除されることを意味します。

永続ノードとは、ノードが作成された後に、ノードを作成したクライアントと Zookeeper サーバー間のセッションが失敗した場合でも (たとえば、接続が切断された場合)、ノードは削除されないことを意味します。ノードは、クライアントがノードの削除要求を積極的に開始した場合にのみ削除されます。

順序付きノードと呼ばれる別のタイプのノードもあります。このタイプのノードは、作成時にシリアル番号が付与され、このシリアル番号は自動的に増加します。順序付けられたノードは、順序付けられた一時ノードまたは順序付けられた永続ノードのいずれかになります。

Zookeeper 内のすべてのデータはノードを通じて保存され、そのディレクトリ構造は以下に示すようにファイル ツリーのようになります。

飼育員の構造

図のロック、レジスタ、およびデータ ディレクトリはカスタム作成され、さまざまなビジネスのデータを保存するために使用されます。たとえば、locks は分散ロックに関連する情報を格納するために使用され、register は登録センターに関連するデータを格納するために使用されます。

ここで、分散ロックを取得したいと思います。このロックの K を K1 と呼ぶことにします。ここでクライアント a が存在し、分散ロックを作成するために JK に移動します。分散ロック K1 を作成すると、nex ディレクトリの下に K1 というフォルダーと K1 というファイルが作成されます。ここで、分散ロックを取得したいと思います。このロックの K を K1 と呼ぶことにします。ここでクライアント a が存在し、分散ロックを作成するために JK に移動します。分散ロック K1 を作成すると、nex ディレクトリの下に K1 というフォルダーと K1 というファイルが作成されます。

達成方法

Zookeeper を使用して分散ロックを実装するには、次の 2 つのソリューションがあります。1. 一時ノードに基づく実装。 2. 一時的な順次ノードに基づく実装。このソリューションの実装原理を以下に紹介します。

まず、すべての分散ロックがロック ディレクトリに保存されていると仮定します。

解決策 1: 一時ノードに基づく (非推奨)

クライアント A、B、C がすべて同じ分散ロック Key1 を取得すると仮定します。

まず、クライアント A は分散ロック Key1 を取得し、次にロック ディレクトリに Key1 という ZNode ノードを作成しようとします。この時点でロック ディレクトリに ZNode Key1 がない場合、クライアント A は Key1 ノードを正常に作成できます。つまり、クライアント A は Key1 ロックを正常に取得できます。

図1

同時に、クライアント B もロック Key1 を取得するようになります。クライアント B は、ロック ディレクトリに Key1 ZNode ノードも作成する必要があります。この時点で、Key1 ZNode ノードがすでに存在するため、クライアント B はそれを作成できません。作成に失敗すると、クライアント B はロックを取得できないため、この時点でクライアント B は独自のリスナー (ウォッチャー) を Zookeeper に登録し、ZNode ノード Key1 の変更を監視します (Key1 ノードが変更されると、Zookeeper はクライアント B に通知します)。

クライアント A とクライアント B が同時に Zookeeper を要求した場合、Zookeeper には、クライアントの 1 つだけが ZNode ノード Key1 を正常に作成できるようにするメカニズムがあります。

図2

同様に、クライアント C が Key1 ロックを取得しようとしても、ロックを取得できません。また、Key1 ZNode ノードの変更を監視するために、ZK に独自の Watcher を登録します。

クライアント A は独自のビジネス ロジックの処理を完了すると、ロックを解除します。ロックを解除すると、クライアントは Key1 ノードを削除します。ノードが正常に削除された場合、ロックが正常に解除されたことを意味します。 Key1 ノードが削除されると、Zookeeper は Key1 ノードを監視するすべてのクライアント、つまりクライアント B と C に通知します。

クライアント B と C は通知を受信し、Key1 ノードが変更されたことを認識すると、再度 Zookeeper を要求し、locks ディレクトリの下に Key1 ノードを作成しようとします。現時点では、Key1 ノードを正常に作成できるクライアントは 1 つだけです。クライアント B が正常に作成された場合、クライアント B がロックを正常に取得したことを意味します。クライアント C がロックの取得に失敗した場合、Key1 ノードの変更を監視し続けます。

図3

推奨されない理由

上記は、Zookeeper 分散ロックを実装するための一時ノードに基づくソリューションですが、このソリューションは通常は推奨されません。なぜ?なぜなら、この解決策を使用すると群集効果という大きな問題が生じるからです。

それはどういう意味ですか?

上記のプロセスから、クライアント A がロックを正常に解放すると、Zookeeper は Key1 ノードをリッスンしているすべてのクライアントに通知する必要があることがわかります。上記の例ではクライアント B と C しかありませんが、実際のアプリケーションではクライアントの数は数百、数千、あるいはそれ以上になる場合があります。現時点で Zookeeper は数百または数千のリクエストを送信する必要があります。まず第一に、この効率は明らかに高くありません。さらに、分散ロックの競争が激しくなると、Zookeeper のネットワーク カードがこの時点で圧倒される可能性が高くなります。さらに、システムには Key1 だけでなく、Key2、Key3、Key4 などが存在する可能性があります。これらのロックも競合の対象となる可能性があり、Zookeeper にさらに負担がかかります。

このプロセスでは、分散ロックを取得するときにクライアントの 1 つしかロックを取得できないため、これが不合理であることがはっきりとわかります。したがって、Key1 ノードが削除された場合は、他のクライアントにロックを取得するように通知する必要があります。現時点ですべてのクライアントに通知する必要がありますか?

明らかにこれは必要ではなく、クライアントの 1 つに通知するだけで済みます。したがって、オプション 2 が出現しました。

ソリューション2: 一時的なシーケンシャルノードに基づく実装(推奨)

一時シーケンシャルノードに基づいて分散ロックを実装する場合、一時ノード Key1 は Linux ディレクトリの下に作成されません。代わりに、まず locks ディレクトリの下に Key1 ディレクトリを作成し、次に Key1 ディレクトリに一時シーケンス ノードを作成します。

クライアント A が分散ロック Key1 を取得したと仮定します。このとき、クライアント A は Key1 ディレクトリに一時シーケンス ノードを作成します。この一時シーケンス ノードのシーケンス番号は 001 です。

次に、クライアント A は、作成した一時シーケンス ノード 001 が Key1 ディレクトリ内で最小のシーケンス番号を持っているかどうかを判断します。最小の場合、クライアント A がロックを正常に取得したことを意味します。

次に、クライアント B も分散ロック Key1 を取得し、Key1 ディレクトリの下に一時シーケンス ノードも作成します。この時点で自動増分シーケンス番号は 002 になっており、以前に 001 が作成されているため、クライアント B は一時シーケンス ノード 002 を作成します。

図4

同様に、クライアント B は、作成した一時シーケンス ノード 002 が現在の Key1 ディレクトリ内で最小のシーケンス番号を持つ一時ノードであるかどうかも判断します。明らかにそうではありません。その前に一時シーケンス ノード 001 があるため、クライアント B はこの時点でロックを取得できません。

クライアント B がロックの取得に失敗すると、クライアント B は Zookeeper に独自のリスナーを登録し、そのリスナーは以前の一時シーケンス ノード、つまりシーケンス ノード 001 をリッスンします。

図5

このとき、クライアント C も分散ロック Key1 を取得する場合、Key ディレクトリに一時シーケンス ノード 003 を作成します。同様に、003 は最小のシーケンス番号を持つ一時シーケンス ノードではないため、クライアント C もロックを取得できず、一時シーケンス ノード 002 をリッスンすることになります。

クライアント A はビジネス ロジックの処理を完了すると、ロックを解除します。ロックを解除する操作は、クライアント A がディレクトリ Key1 の下に作成した一時シーケンス ノードを削除すること、つまり一時シーケンス ノード 001 を削除することです。シーケンス ノード 001 が削除されると、Zookeeper はシーケンス ノード 001 を監視するすべてのクライアントに通知します。つまり、クライアント B に通知します。クライアント B は Zookeeper から通知を受信した後、自分が作成した一時シーケンス ノード 002 が現在の Key1 ディレクトリ内で最もシーケンス番号が小さい一時シーケンス ノードであるかどうかを判断します。この時点で、シーケンスノード 001 は存在しなくなっているため、002 が最小であることは明らかであり、クライアント B はロックを正常に取得します。

図6

同様に、クライアント B がロックを解除すると、002 が削除されます。002 が削除された後、Zookeeper はクライアント C に通知します。クライアント C は、現在作成した一時シーケンス ノード 003 が Key1 ディレクトリ内で最小のシーケンス番号であることを検出するため、クライアント C はロックを正常に取得します。

考える

クライアント A がロックを正常に取得した後、長時間ロックを解放しないか、クライアント A が配置されているマシンがクラッシュするか、クライアント A が配置されているマシンでネットワーク障害が発生します。この時何が起こるのでしょうか?

クライアント A が配置されているマシンがクラッシュしたり、ネットワーク障害が発生したりして、Zookeeper との通信が長時間行われない場合、クライアント A と Zookeeper の間に作成されたセッションは無効になります。このセッションが無効になると、Zookeeper はクライアント A によって作成された一時シーケンス ノードを直接削除します。この時点で、他のクライアントは正常にロックを取得できます。

<<:  Kubernetes を本番環境で 2 年間使用して学んだ教訓

>>:  [Sticky JVM] 5年ぶりにJVMのロードメカニズムを知る時が来ました!

推薦する

最近の出来事から交通大手の事業を考察する

検索業界では、多くの友人がトラフィックを開発の第一優先事項と考えています。草の根ウェブマスターの中に...

ウェブサイトが含まれない問題の解決方法とその解決戦略

現在、新しい Web サイトの Web マスターにとって最も頭を悩ませている問題は、インクルードの問...

OpenStack Newton がリリース、EasyStack コアコード貢献が中国で第 1 位に

今週、OpenStack は 14 番目のバージョンである Newton を正式にリリースしました。...

Baidu の 6 月の狂乱、まだ持ちこたえられるか?

今年の端午節は多くのウェブマスターにとって暗い日になるだろうと私は信じています。木曜日の定期更新によ...

ウェブサイトのランキング低下の主な理由について簡単に説明します(分析結果)

みなさんこんにちは。私はバーチャルリアリティウェブサイトデザインです。最近、私のウェブサイトのランキ...

盲目的にウェブサイトを最適化するよりも、ユーザーエクスペリエンスを良くする方が良い

昨日(2013年2月19日)BaiduのGreen Radish Algorithmがリリースされ、...

A5最適化グループ: フォーラムを最適化する際に注意すべき点

ウェブサイトの構築中、ほとんどのウェブマスターはフォーラムの構築と最適化に消極的です。その理由は何で...

私のドメイン名登録履歴 ウェブマスターはどのようにしてドメイン名のセキュリティを確保できますか?

先日、ドメイン名をめぐって「ウーロン権保護」事件が発生した。かつて「シーメンス冷蔵庫を破壊」してネッ...

検索エンジンに好まれるウェブサイトの作り方

検索エンジン最適化は、ウェブマスターにとって常に永遠のテーマです。多くのウェブマスターは、検索エンジ...

directspace-$5/KVM/1g メモリ/40g SSD/2T トラフィック/10G ポート

Directspace の Web サイトが刷新され、コンピューター ルームがアップグレードされまし...

「クラウド戦略」は企業のデジタル変革の重要な柱となる

今日、世界はデジタル経済の時代に突入し、政府や企業もデジタル変革の段階に入っています。クラウドコンピ...

百度はランキングを決定する要因を知っている

Baidu Knows のプロモーションは、一方ではブランドの影響力を高め、他方では直接トラフィック...

マーケティングプロモーションがわからなくて困っていませんか? A5ベンチャーネットワークは618のトラフィック獲得をお手伝いします

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています今年の6月...