この記事を読むのに必要な時間はたった 10 分です。 現在、分散ロックを実装するための一般的なソリューションは、データベース、Redis、Zookeeper に基づくソリューションの 3 つです。最初の 2 つの解決策については、インターネット上に参考になる情報が多数ありますが、この記事では詳しく説明しません。 Zookeeper を使用して分散ロックを実装する方法を見てみましょう。 Zookeeper とは何ですか? Zookeeper (業界では zk と略される) は、構成管理、分散コラボレーション、および命名機能を提供する集中型サービスです。これらの機能は、分散システムにおいて非常に低レベルかつ不可欠な基本機能です。しかし、これらの機能を自社で実装し、高スループット、低レイテンシ、一貫性、可用性を実現するのは実際には非常に困難です。したがって、Zookeeper はこれらの機能を提供しており、開発者は Zookeeper 上に独自の分散システムを構築します。 ZooKeeper の実装は比較的複雑ですが、ZooKeeper が提供するモデルの抽象化は非常にシンプルです。 Zookeeper は、複数レベルのノード名前空間 (ノードは znode と呼ばれます) を提供します。各ノードはスラッシュ (/) で区切られたパスで表され、各ノードには親ノード (ルート ノードを除く) があり、これはファイル システムに非常に似ています。たとえば、/foo/doo は、親ノードが /foo で、親ノードが / である znode を表します。また、/ はルート ノードであり、親ノードはありません。ファイル システムとは異なり、これらのノードはすべて関連データで設定できますが、ファイル システムではファイル ノードのみがデータを保存でき、ディレクトリ ノードはデータを保存できません。高いスループットと低いレイテンシを確保するために、Zookeeper はこのツリー状のディレクトリ構造をメモリ内に維持します。この機能により、Zookeeper は大量のデータの保存に使用できなくなります。各ノードのデータ保存上限は1Mです。 高可用性を確保するには、Zookeeper をクラスター形式で展開する必要があります。これにより、クラスター内のほとんどのマシンが利用可能である限り (特定のマシン障害を許容できる)、Zookeeper 自体も引き続き利用可能になります。 Zookeeper を使用する場合、クライアントはクラスター マシンのリストを認識し、クラスター内のマシンとの TCP 接続を確立してサービスを使用する必要があります。クライアントはこの TCP 接続を使用して、要求の送信、結果の取得、監視イベントの取得、ハートビート パケットの送信を行います。この接続が異常切断された場合、クライアントは別のマシンに接続できます。 簡略化されたアーキテクチャ図は次のとおりです。 クライアントの読み取り要求は、クラスター内の任意のマシンで処理できます。読み取り要求によってノードにリスナーが登録されると、そのリスナーも接続された Zookeeper マシンによって処理されます。書き込み要求の場合、これらの要求は同時に他の Zookeeper マシンに送信され、合意に達した後にのみ要求が成功として返されます。したがって、ZooKeeper クラスター マシンの数が増えると、読み取り要求のスループットは増加しますが、書き込み要求のスループットは減少します。 順序は Zookeeper にとって非常に重要な機能です。すべての更新はグローバルに順序付けられ、各更新には zxid (Zookeeper Transaction Id) と呼ばれる一意のタイムスタンプが付きます。読み取り要求は更新に対してのみ順序付けられます。つまり、読み取り要求の返される結果には、この Zookeeper*** の zxid が含まれます。 Zookeeper を使用して分散ロックを実装するにはどうすればよいですか? アルゴリズムのフローを説明する前に、ZooKeeper のノードの興味深いプロパティをいくつか見てみましょう。
以下は、ロック スペースのルート ノードが /lock であると仮定して、Zookeeper を使用して分散ロックを実装するアルゴリズム フローを説明します。
ステップ 1 で作成された一時ノードにより、障害が発生した場合でもロックを解除できるようになります。次のシナリオを考えてみましょう。クライアント a によって現在作成されている子ノードがシリアル番号が最も小さいノードである場合、クライアントが配置されているマシンはロックを取得した後にクラッシュし、クライアントは子ノードを積極的に削除しません。最大のシリアル番号を持つノードが作成されると、ロックは解放されず、デッドロックが発生します。一時ノードが作成されるため、クライアントがクラッシュした後、一定時間が経過すると、Zookeeper はクライアントのハートビート パケットを受信できなくなり、セッションが無効であると判断し、一時ノードを削除してロックを解除します。 さらに、注意深い友人は、ステップ 2 で子ノード リストを取得し、リスナーを設定する際の原子性の問題を考えるかもしれません。次のようなシナリオを考えてみましょう。クライアント a の対応する子ノードは /lock/lock-0000000000 であり、クライアント b の対応する子ノードは /lock/lock-00000000001 です。クライアント b が子ノード リストを取得すると、それが最小のシーケンス番号を持つものではないことがわかります。ただし、リスナーを設定する前に、クライアント a はビジネス プロセスを完了し、子ノード /lock/lock-0000000000 を削除します。クライアント b によって設定されたリスナーはこのイベントを失って永久に待機するのではないでしょうか?この問題は存在しません。 ZooKeeper が提供する API でのリスナー設定操作は、読み取り操作と同時にアトミックに実行されるため、子ノード リストの読み取り時に同時にリスナーが設定され、イベントが失われないようにします。 ***、このアルゴリズムには優れた最適化ポイントがあります。ロックを待機しているノードが 1000 個ある場合、ロックを取得したクライアントがロックを解放すると、これらの 1000 個のクライアントが起動されます。この状況は「群集効果」と呼ばれます。この群集効果により、Zookeeper は 1000 のクライアントに通知する必要があり、他の操作がブロックされます。最良のケースでは、新しい最小ノードに対応するクライアントのみが起動されるはずです。何をすべきでしょうか?イベント監視を設定する場合、各クライアントは直前の子ノードに対してイベント監視を設定する必要があります。たとえば、子ノード リストは /lock/lock-0000000000、/lock/lock-0000000001、/lock/lock-0000000002 です。シーケンス番号 1 のクライアントは、シーケンス番号 0 の子ノードの削除メッセージをリッスンし、シーケンス番号 2 のクライアントは、シーケンス番号 1 の子ノードの削除メッセージをリッスンします。 したがって、調整された分散ロック アルゴリズムのプロセスは次のようになります。
Curatorのソースコード解析 Zookeeper ネイティブ クライアントによって公開される API は非常に簡潔ですが、分散ロックを実装するのは依然として面倒です... Curator オープン ソース プロジェクトによって提供される Zookeeper 分散ロック実装を直接使用できます。 次のパッケージ (Maven ベース) を導入するだけです。
そうすれば使えますよ!コードは次のとおりです。
主要なコア操作は mutex.acquire() と mutex.release() だけであることがわかります。これは非常に便利です。 ロックを取得するソースコードの実装を分析してみましょう。取得方法は以下の通りです。
ここで注意すべき点が1つあります。 Zookeeper との通信で例外が発生した場合、 acquire は直接例外をスローするため、ユーザーは再試行戦略を自分で作成する必要があります。このコードは internalLock(-1, null) を呼び出し、パラメータはロックがブロックされ、占有されているときに待機することを示します。 internalLock のコードは次のとおりです。
特定のコメントがコードに追加され、展開されません。 Zookeeper がロックを取得する具体的な実装を見てみましょう。
上記のコードには主に 2 つのステップがあります。
internalLockLoop がロックとブロッキング待機をどのように決定するかを見てみましょう。ここでは無関係なコードが削除され、メイン プロセスのみが残ります。
具体的なロジックはコメントに示されており、ここでは繰り返さないことにします。コードに設定されたイベント リスナーは、イベント コールバックが発生したときに現在のスレッドを起動して再スピンするように notifiesAll するだけです。比較的単純なので拡張されません。 その上。 |
<<: クラウド時代のパフォーマンス監視戦略の隠れた利点を明らかにする
9月3日早朝、アップルは著名人のiCloudアカウントのハッキングに対し、iCloudクラウドストレ...
[51CTO.com クイック翻訳] Kubernetes は、市場で最も強力で柔軟なコンテナ クラ...
[[396901]]前回の記事では、システムパフォーマンスを向上させるためのキャッシュを行うローカル...
最近、モバイル電源ネットワークを構築しました。Web サイトを構築する実際のプロセス中に、うまくいか...
真剣に考えたことがあるか分かりませんが、オンラインビジネスを営む私たちにとって、その核心は実は「信頼...
過去2年間で、ライブストリーミング電子商取引は活況を呈する新しい経済産業となり、ライブストリーミング...
この記事「WeChatは左へ、QQは右へ」は、かつてワイヤレス部門で働き、現在はモバイル電子商取引の...
1995 年以降に生まれた世界中の人々の 98% は、通常、実店舗での買い物を好みます。これは、オン...
ネット上で友人たちが「プロジェクト」を見つけて「ウェブサイト」を作ることについて話しているのをよく見...
レコード業界は、チャンネルに集団で挑戦したいと考えている収益分配率の調整はレコード業界を救えるか?こ...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています今日、Xi...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています8月8日、...
少し前に、突然ウェブサイトがダウングレードされていることに気づきました。百度は医療サイトに対して常に...
2019年第1四半期の世界のモバイル広告市場の主な傾向は次のとおりです。 1. 動画の牽引によりモバ...
文/ビアン・ハイフェンスポーツ競技では、審判のミスの発生によって試合の最終結果が左右されることがよく...