分散ロックの原理は、私たちが普段話しているロックと基本的に同じです。目的は、複数のスレッドが同時に実行されている場合に、1 つのスレッドだけが同時にビジネス、メソッド、または変数を操作するようにすることです。 プロセス、つまり JVM またはアプリケーションでは、制御を処理するのは簡単です。 jdk java.util 並行性パッケージには、これを処理できる Synchronized キーワードや Lock ロックなどのロックメソッドが用意されています。 ただし、現在のアプリケーションが 1 台のサーバーにのみデプロイされている場合、同時実行性は非常に低くなります。一度に数万件ものリクエストがあった場合、サーバーが過負荷になり麻痺してしまう可能性が高くなります。 ダブルイレブンや大晦日の夜10時にアリペイの紅包を配布するなどのビジネスシナリオを考えてみましょう。当然、これらの業務を同時に処理するには複数のサーバーが必要になります。これらのサービスは、同時に数百台のサーバーによって処理される場合があります。 しかし、考えてみてください。紅包配布ビジネスを扱うサーバーが 100 台あり、紅包が 1 億個あり、1,000 万人がランダムな量でそれを分配すると仮定すると、このビジネス シナリオでは、これらの 1,000 万人が配布した紅包の合計量が 1 億個になるようにする必要がありますか?
うまく処理されず、全員が100万ドルを受け取ることになったら、ジャック・マーはおそらく旧正月の初日に破産を宣言しなければならないだろう。 通常のロックでは何が起こりますか? まず、クラスターを構築する必要がある理由について説明します。簡単に言えば、需要(同時リクエスト量)が増加し、1 人のワーカーの処理能力が制限されると、より多くのワーカーを募集して一緒に処理することができます。 1,000 万件のリクエストが 100 台のサーバーに均等に分散され、各サーバーが 10 万件のリクエストを受信すると仮定します。 これらの 100,000 件のリクエストは同じ秒数内に届いたわけではなく、1 ~ 2 時間以内に届いた可能性があります。 3月30日の夜に紅包を開けるようなものだと想像してください。10時20分にすぐに開けた人もいれば、12時まで開けたことに気づかなかった人もいます。 この場合、1 秒あたりの平均リクエスト数は 1,000 未満であり、通常のサーバーはまだこの負荷に耐えることができます。
これは、各サーバーに 1 億を分配すること、つまり 10 万人のユーザーが 1 億を共有し、合計 100 台のサーバーがあるため、100 億が必要になることに相当します。 もしこれが本当なら、ジャック・マーは破産しないものの(***の統計によると、ジャック・マーは2,300億人民元を保有している)、ボーナスを受け取る開発プロジェクトチームと製品マネージャーは破産する可能性があります。 簡略化された構造図は次のとおりです。 分散ロックをどのように処理しますか? したがって、この問題を解決するには、1,000 万人のユーザーが 100 億ではなく 1 億だけを共有できるようにします。このとき、分散ロックが役立ちます。 分散ロックはクラスター全体をアプリケーションとして扱うことができるため、ロックはサービス内ではなく各サービスから独立している必要があります。 最初のサーバーがユーザー 1 からのリクエストを受信した後、独自のアプリケーションで配布可能な金額を判断できるだけでなく、1 億枚の紅包の管理を特に担当する人物 (サービス) に外部リクエストを送信して、「100 元欲しいので、100 元ください」と依頼する必要があるとします。 紅包(サービス)を担当する女の子は、まだ1億あるのを見て、「わかりました。100元あげます。99,999,900元残ります」と言いました。 2番目のリクエストが到着した後、サーバー2で受信され、赤い封筒を管理する女の子に、10元を分けたいと引き続き尋ねます。紅包を管理する女の子が最初に確認し、99999900元が残っていることがわかったので、彼女は言いました。「わかりました。10元あげます。それで、残りは99999890元です。」 1000wth リクエストが到着すると、サーバー 100 がリクエストを受け取り、赤い封筒を管理する女の子に「100 個欲しい」と尋ね続けます。女の子は目を回してあなたに言います。「あと1元しかありません。受け取るか受け取らないかはあなた次第です。」現時点では、1元しかお渡しできません(1元もお金です。辛いバーを買うには十分です)。 これらのリクエスト番号 1 と 2 は実行順序を表すものではありません。正式なシナリオでは、100 台のサーバーがあり、各サーバーには、赤い封筒の管理を担当する女の子 (サービス) へのアクセス要求が保持されます。 すると、紅包担当の女の子は同時に100件のリクエストを受け取ることになります。このとき、赤い封筒を担当する女の子(ボールを投げる)にロックを追加するだけです。 100 人のサーバーのうちロックを獲得した (ボールを掴んだ) 人は誰でも入って来て私に話しかけることができます。私はあなたにその分け前をあげます、そして他の人たちはただ待っていてください。 上記の分散ロック処理の後、ジャック・マーはようやく安心し、紅封筒チームのメンバー全員に鶏の脚を与えることにしました。 簡略化された構造図は次のとおりです。 分散ロックの実装は何ですか? 分散ロックの実装に関しては、データベース方式、Redis 分散ロック、Zookeeper 分散ロックなど、まだまだたくさんあります。 Redis を分散ロックとして使用すると、上の図の「赤い封筒を担当する女の子 (サービス)」を Redis に置き換えることができます。想像力を働かせてください。 ①Redis が分散ロックを実装できるのはなぜですか? まず、Redis はシングルスレッドです。ここでのシングルスレッドとは、ネットワーク要求モジュールが 1 つのスレッドを使用する (したがって、同時実行の安全性を考慮する必要がない)、つまり、1 つのスレッドがすべてのネットワーク要求を処理し、他のモジュールは引き続き複数のスレッドを使用することを意味します。 実際の操作では、プロセスはおおよそ次のようになります。サーバー 1 は、赤い封筒を送った女の子、つまり Redis にアクセスしたいので、「setnx key value」操作を通じて Redis にキーを設定します。値が何であるかは問題ではありません。重要なのは、キー、つまりマークがなければならないということです。 すべてのサーバーが同じキーを持っている限り、このキーを好きなように呼ぶことができます。 以下のように設定するとします。 すると、成功を意味する 1 が返されることがわかります。 次のように、同じキーを設定するための別のリクエストが届いた場合: このとき、失敗を意味する 0 が返されます。 次に、この操作を使用して、現時点でロックを取得できるかどうか、または「赤い封筒を送る責任がある女の子」を訪問できるかどうかを判断できます。 1 が返された場合は、後続のロジックの実行を開始します。 0 が返された場合は、すでに誰かに占有されていることを意味するので、待機を継続する必要があります。 サーバー 1 はロックを取得した後、ビジネス処理を実行し、完了したら次の図に示すようにロックを解除する必要があります。 削除が成功すると 1 が返され、他のサーバーは上記の手順を繰り返してこのキーを設定し、ロックを取得する目的を達成できます。 もちろん、上記の操作は Redis クライアントで直接実行されます。プログラムを通じて呼び出される場合は、このように記述することはできません。たとえば、Java は Jedis を介して呼び出す必要がありますが、処理ロジック全体は基本的に同じです。 上記の方法により、分散ロックの問題は解決したように見えますが、何か問題があるかどうか考えてみましょう。 はい、まだ問題が残っています。デッドロックが発生する可能性があります。たとえば、サーバー 1 がセットアップされ、ロックを取得した後、突然クラッシュします。 その後のキー削除操作は実行できません。このキーは常に Redis に存在します。他のサーバーがそれをチェックするたびに、0 が返されます。誰かがロックを使用していると判断され、待機する必要があります。 このデッドロック問題を解決するには、キーの有効期間を設定する必要があります。設定方法は2つあります: 1 つ目は、キーを設定した後にキーの有効期間「有効期限切れキータイムアウト」を直接設定し、キーのタイムアウト期間を秒単位で設定することです。この時間が経過すると、デッドロックを回避するためにロックは自動的に解除されます。 この方法は、ロックの有効期間を Redis に渡して制御することと同じです。時間が経過してもキーを削除していない場合、Redis が直接キーを削除し、他のサーバーは引き続き Setnx を使用してロックを取得できます。 2 番目の方法は、キーを削除する権限を他のサーバーに付与することです。この場合、Value 値が必要になります。たとえば、サーバー 1 は値、つまりタイムアウトを現在の時刻 + 1 秒に設定します。 この時点で、サーバー 2 は Get を通じて、時間が現在のシステム時間を超えていることを検出します。これは、サーバー 1 がロックを解除しておらず、サーバー 1 に問題がある可能性があることを意味します。サーバー 2 は Delete Key 操作の実行を開始し、Setnx 操作の実行を続行します。 しかし、ここで問題があります。つまり、サーバー 2 がサーバー 1 のタイムアウトを検出するだけでなく、サーバー 3 でも検出される可能性があるということです。サーバー 2 の Setnx 操作が完了し、サーバー 3 が削除された場合、サーバー 3 でも正常に Setnx を実行できますか? つまり、サーバー 2 とサーバー 3 の両方がロックを取得したことになりますが、これは大きな問題です。こういう時どうすればいいでしょうか? このとき、「GETSET キー値」コマンドを使用する必要があります。このコマンドの意味は、現在のキー値を取得し、新しい値を設定することです。 サーバー 2 がキーの有効期限が切れていることを検出し、getset コマンドの呼び出しを開始し、取得した時間を使用してキーの有効期限が切れているかどうかを判断します。取得した時間がまだ期限切れになっている場合は、ロックが取得されたことを意味します。 そうでない場合は、サービス 2 が getset を実行する前に、サーバー 3 もロックの有効期限が切れていることを検出し、サーバー 2 より前に getset 操作を実行して有効期限をリセットすることになります。 その後、サーバー 2 は後続の操作を中止し、サーバー 3 がロックを解除するか、キーの有効期限が切れたかどうかを監視し続ける必要があります。 実はここには小さな問題があります。サーバー 3 は既に有効期間を変更しています。ロックを取得した後、サーバー 2 も有効期間を変更しましたが、ロックを取得できませんでした。 ただし、サーバー 3 に基づいて有効期間が延長されましたが、影響はまだ非常に小さく、ほとんど無視できます。 ②Zookeeper が分散ロックを実装できるのはなぜですか? Baidu Encyclopedia では次のように紹介しています: ZooKeeper は、分散型のオープンソース分散アプリケーション調整サービスです。これは、Google の Chubby のオープンソース実装であり、Hadoop と Hbase の重要なコンポーネントです。 ZooKeeper を初めて使う人にとっては、ZooKeeper がコンピュータのファイル システムのようなものだということがお分かりいただけると思います。ドライブ D にフォルダー a を作成し、フォルダー a にフォルダー a1 と a2 を続けて作成できます。 では、私たちのファイルシステムの特徴は何でしょうか?つまり、同じディレクトリ内でファイル名を繰り返すことはできません。これは ZooKeeper の場合も同様です。 ZooKeeper 内のすべてのノード、つまりフォルダーは Znode と呼ばれ、この Znode ノードにデータを保存できます。 「create /zkjjj nice」でノードを作成できます。このコマンドは、ルート ディレクトリに nice の値を持つ zkjjj ノードを作成することを意味します。 ここでの値は、先ほど述べた Redis の値と同じで、意味はなく、好きな値を指定できます。 さらに、ZooKeeper は次の 4 種類のノードを作成できます。
まず、永続ノードと一時ノードの違いについて説明します。
Zookeeper には監視メカニズムがあります。クライアントは、関心のあるディレクトリ ノードを監視するために登録します。ディレクトリ ノードが変更されると (データの変更、削除、サブディレクトリ ノードの追加または削除)、Zookeeper はクライアントに通知します。 Zookeeper をロックするにはどうすればいいですか? 次に、上記の配当分配シナリオに基づいて、Zookeeper をロックインする方法について説明します。 サーバー 1 がノード /zkjjj を正常に作成し、サーバー 1 がロックを取得したとします。サーバー 2 が同じロックを再度作成しようとすると、失敗します。現時点では、このノードの変更のみを監視できます。 サーバー 1 が業務の処理を終了し、ノードを削除すると、通知が送信され、同じノードが作成され、業務を処理するためのロックが取得されてから、ノードが削除されます。後続の 100 台のサーバーも同様です。 ここで、100 台のサーバーは上記のノード作成操作を 1 つずつ実行するのではなく、同時に実行することに注意してください。サーバー 1 が正常に作成されると、残りの 99 台がこのノードをリッスンして通知を待機するように登録されます。 しかし、ここでまだ問題があり、デッドロックがまだ発生することに気付きましたか? サーバー 1 がノードの作成後にクラッシュし、削除に失敗すると、他の 99 台のサーバーは通知を待機し続け、それで終わりになります。 このとき、一時的なノードが必要になります。前に述べたように、一時ノードの特性は、クライアントが切断されると失われることです。 つまり、サーバー 1 がノードを作成した後、サーバー 1 がクラッシュすると、そのノードは自動的に削除され、後続のサーバーが引き続きノードを作成し、ロックを取得できるようになります。 しかし、衝撃的な群集効果という点にも注意を払う必要があるかもしれません。非常に単純な例を挙げると、ハトの群れの真ん中に食べ物を投げると、最終的に食べ物をつかむのは 1 羽のハトだけであっても、すべてのハトが驚いて食べ物を奪い合い、つかまなかったハトは… つまり、サーバー 1 ノードに変更があった場合、残りの 99 台のサーバーに通知されますが、最終的に正常に作成されるのは 1 台のサーバーのみなので、98 台はまだ監視を待つ必要があります。この状況に対処するには、一時的なシーケンシャル ノードが必要です。 一般的な意味は、以前は 99 台のサーバーすべてが 1 つのノードをリッスンしていましたが、現在は各サーバーがその前にあるノードをリッスンするということです。 100 台のサーバーが同時にリクエストを送信すると、/zkjjj ノードの下に、/zkjjj/000000001、/zkjjj/000000002、…、/zkjjj/000000100 までの 100 個の一時的な連続ノードが作成されます。この数値は、ロックを取得する順序を設定することと同じです。 ノード 001 が処理されて削除されると、ノード 002 が通知を受信し、ロックを取得して実行を開始し、実行が完了したらノードを削除して、ノード 003 に通知する、という処理が行われます。 |
<<: 3年間のJavaバックエンド開発では、JVMを知っておく必要があります
>>: 中国におけるSAP: 業界の変革とアップグレードを支援
古いドメイン名について言えば、古いドメイン名の重みについて考えます。ウェブマスターの心の中では、古い...
ご存知のとおり、クラウド コンピューティングの世界は、IaaS、SaaS、PaaS で構成されていま...
中国マイクロクレジット連盟の事務局長である白成宇氏は、P2Pプラットフォームは借り手と投資家の間の取...
6月28日、2018 Mobile World Congress(上海)において、UCloudとCh...
サイト クラスターの主な目的は、検索エンジンを通じて大量のトラフィックを獲得したり、メイン サイトへ...
従来の PC ソフトウェア開発者は、モバイル インターネット分野への変革を加速する必要があり、さもな...
私は多くの最適化ウェブサイトで多くの記事を読みましたが、それらはすべて一般的な理論的な知識であり、誰...
#ニュース# BandwagonHost Japan VPS が、日本の SoftBank 回線を使...
「クラウドデスクトップを通じて、これまでは機密保持の要件によりインターネット上では知ることのできなか...
最近、世界をリードするロボティック・プロセス・オートメーション(RPA)プラットフォームであるUiP...
第2四半期の業務・生産再開に伴い、エンターテインメント生放送市場は徐々に「爆発的成長期」から「調整期...
国内の仮想ホスト市場は巨大なケーキであり、多くの海外のウェブサイトスペースプロバイダーが中国市場を獲...
最近、李二仔思と喬石桂子堅の対戦を見てきました。私もソーシャルメディアマーケティングを試してみました...
オレゴンは、米国西海岸、カリフォルニア州のすぐ上に位置しています。ベンドは、オレゴン州中央部にありま...
4月23日の網易科技報によると、Ganji.comが共同購入を断念した後、テンセントが出資するFtu...