RedisやZooKeeperなどの分散ロックの原理に関する考察

RedisやZooKeeperなどの分散ロックの原理に関する考察

まず、分散ロックの原理は、私たちが普段話しているロックと基本的に同じです。目的は、複数のスレッドが同時に実行されている場合に、1 つのスレッドだけが同時にビジネス、メソッド、または変数を操作するようにすることです。

[[325805]]

プロセス、つまり JVM またはアプリケーションでは、制御を処理するのは簡単です。 jdk java.util 並行性パッケージには、これを処理できる synchronized キーワードや Lock ロックなど、ロックを追加するためのメソッドが用意されています。

ただし、現在のアプリケーションが 1 台のサーバーにのみデプロイされている場合、同時実行性は非常に低くなります。一度に数万件ものリクエストがあった場合、サーバーが過負荷になり麻痺してしまう可能性が高くなります。

ダブル11と30日の夜10時にアリペイ紅包などのビジネスシーンを考えてみましょう。当然、これらの業務を同時に処理するには複数のサーバーが必要になります。これらのサービスは、同時に数百台のサーバーによって処理される可能性があります。

でも、よく考えてみてください。紅包配布ビジネスを扱うサーバーが 100 台あり、紅包が 1 億枚あり、1,000 万人がランダムな量で紅包を配布すると仮定すると、このビジネス シナリオでは、これらの 1,000 万人に配布される紅包の合計量が 1 億枚になるようにする必要がありますか?

もし全員が100万元を受け取ったら、ジャック・マーはおそらく旧正月の初日に破産を宣言しなければならないだろう。

1. 従来のロックを使用するとどうなるでしょうか?

まず、クラスターを構築する必要がある理由について説明します。簡単に言えば、需要(同時リクエスト量)が増加し、1 人のワーカーの処理能力が限界に達したため、さらにワーカーを募集して一緒に処理するということです。

1000万件のリクエストが100台のサーバーに均等に分散され、各サーバーが10万件のリクエストを受信すると仮定します(これらの10万件のリクエストは同じ秒ではなく、1〜2時間以内に発生する可能性があります。30日の夜に赤い封筒を開けるのと同じように考えてください。10時20分に始まると、すぐに開ける人もいれば、12時まで待ってから開けることを覚えている人もいます〜)

この場合、1 秒あたりの平均リクエスト数は 1,000 未満であり、通常のサーバーはまだこの負荷に耐えることができます。

最初のリクエストが来たら、ランダムな金額で 1 億の一部を彼に渡す必要がありますか?最初の人が 100 を獲得したとすると、1 億から 100 を引いて、99,999,900 を残す必要がありますか?

2 番目のユーザーがお金を分配しに来ますが、金額はランダムです。今回彼は200元を受け取ります。ということは、残りの 99999900 元から 200 元を差し引いて、99999700 元を残す必要があるということですか?

100,000 人目のユーザーが来て、まだ 1,000,000,000 が残っていることがわかったら、その 1,000,000,000 すべてが彼のものになります。

これは、1 億を各サーバーに分割すること、つまり 10 万人のユーザーが 1 億を共有し、最終的に合計 100 台のサーバーが存在するため、100 億を分割する必要があることに相当します。

もしこれが本当なら、ジャック・マーは破産しないものの(最新の統計によると、ジャック・マーは2,300億人民元を保有している)、ボーナスを受け取る開発プロジェクトチームと製品マネージャーは破産する可能性がある。

簡略化された構造図は次のとおりです。

2. 分散ロックをどのように処理しますか?

したがって、この問題を解決するには、1,000 万人のユーザーが 100 億ではなく 1 億だけを共有できるようにします。このとき、分散ロックが役立ちます。

分散ロックはクラスター全体をアプリケーションとして扱うことができるため、ロックはサービス内ではなく各サービスから独立している必要があります。

最初のサーバーがユーザー 1 からのリクエストを受信した後、この時点では、配布可能な金額を決定するために独自のアプリケーションを使用するだけでは不十分で、1 億枚の紅包の管理を特に担当する人物 (サービス) に外部リクエストを送信して、「100 元欲しいので、100 元ください」と依頼する必要があります。

紅包(サービス)を担当する女の子は、まだ1億元あるのを見て、「わかりました。100元あげます。99,999,900元残ります」と言いました。

2番目のリクエストが到着した後、サーバー2で受信され、赤い封筒を管理する女の子に、10元を分けたいと引き続き尋ねます。紅包を管理する女の子が最初に確認し、まだ99999900枚あることがわかったので、「わかりました。10元あげます」と言いました。残りは99999890元です。

1000元のリクエストが到着すると、サーバー100がリクエストを受け取り、赤い封筒を管理している女の子に「100元欲しいですか?」と尋ね続けます。女の子は目を丸くして「あと1元しかありません。受け取るか受け取らないかはあなた次第です」と言います。現時点では、1元しかお渡しできません(1元もお金です。辛い一口麺を買うには十分です)。

これらのリクエスト番号 1 と 2 は実行順序を表すものではありません。正式なシナリオでは、100 台のサーバーがあり、各サーバーには、赤い封筒の管理を担当する女の子 (サービス) へのアクセス要求が保持されます。すると、紅封筒を管理する女の子は、同時に 100 件のリクエストを受け取ることになります。このとき、赤い封筒を担当する女の子(ボールを投げる)にロックを追加するだけです。 100 人のサーバーのうちロックを獲得した (ボールを掴んだ) 人が私のところに来て話しかけてくれれば、ポイントを差し上げます。他の人はただ待っていてください。

上記の分散ロック処理の後、ジャック・マーはようやく安心し、紅封筒チームのメンバー全員に鶏の脚を与えることにしました。

簡略化された構造図は次のとおりです。

3. 分散ロックの実装は何ですか?

分散ロックの実装に関しては、データベース メソッド、Redis 分散ロック、Zookeeper 分散ロックなど、まだ数多くあります。

分散ロックとして redis を使用する場合、上の図の「赤い封筒を担当する女の子 (サービス)」は redis に置き換えることができます。想像力を働かせてください。

3.1、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. 2 番目の方法は、他のサーバーにキーを削除する権限を与えることです。この場合、値が必要になります。

たとえば、サーバー 1 は値、つまりタイムアウトを現在の時刻 + 1 秒に設定します。この時点で、サーバー 2 は get を通じて、時刻が現在のシステム時刻を超えていることを検出します。これは、サーバー 1 がロックを解除していないことを意味し、サーバー 1 に問題がある可能性があります。

サーバー 2 は、delete キー操作の実行を開始し、setnx 操作の実行を継続します。

しかし、ここで問題があります。つまり、サーバー 2 がサーバー 1 のタイムアウトを検出するだけでなく、サーバー 3 でも検出される可能性があるということです。サーバー 2 の setnx 操作が完了し、次にサーバー 3 が削除された場合、サーバー 3 も正常に setnx できますか?

つまり、サーバー 2 とサーバー 3 の両方がロックを取得したことになりますが、これは大きな問題です。こういう時どうすればいいでしょうか?

このとき、「GETSET キー値」コマンドを使用する必要があります。このコマンドの意味は、現在のキーの値を取得し、新しい値を設定することです。

サーバー 2 がキーの有効期限が切れていることを検出し、getset コマンドの呼び出しを開始し、取得した時間を使用してキーの有効期限が切れているかどうかを判断します。取得した時間がまだ期限切れになっている場合は、ロックが取得されたことを意味します。

そうでない場合は、サービス 2 が getset を実行する前に、サーバー 3 もロックの有効期限が切れていることを検出し、サーバー 2 より前に getset 操作を実行して有効期限をリセットすることになります。

その後、サーバー 2 は後続の操作を中止し、サーバー 3 がロックを解除するか、キーの有効期間が経過したかどうかを監視し続ける必要があります。

実はここには小さな問題があります。サーバー 3 は有効期間を変更しました。ロックを取得した後、サーバー 2 も有効期間を変更しましたが、ロックを取得できませんでした。ただし、有効期間はサーバー 3 に基づいて延長されていますが、この影響は実際には非常に小さく、ほとんど無視できます。

3.2、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 サーバーはノードを保存しなくなります。

シーケンシャルノードについてお話しましょう。連続ノードとは、ノードを作成するときに、ZooKeeper がノードに 0000001、0000002 などの番号を自動的に付けることを意味します。

最後に、Zookeeper には監視メカニズムがあります。クライアントは、関心のあるディレクトリ ノードを監視するために登録します。ディレクトリ ノードが変更されると (データの変更、削除、サブディレクトリ ノードの追加または削除)、Zookeeper はクライアントに通知します。

次に、上記の配当分配シナリオに基づいて、Zookeeper をロックインする方法について説明します。

サーバー 1 がノード /zkjjj を正常に作成し、サーバー 1 がロックを取得したとします。サーバー 2 が同じロックを再度作成しようとすると、失敗します。現時点では、このノードの変更のみを監視できます。

サーバー 1 が業務を処理してノードを削除した後、通知を受け取り、同じノードを作成し、ロックを取得して業務を処理し、ノードを削除します。後続の 100 台のサーバーも同様です。

ここで、100 台のサーバーは上記のノード作成操作を 1 つずつ実行するのではなく、同時に実行することに注意してください。サーバー 1 が正常に作成されると、残りの 99 台がこのノードをリッスンするように登録し、通知を待機するなどします。

しかし、ここでまだ問題があり、デッドロックがまだ発生することに気付きましたか?

サーバー 1 がノードの作成後にクラッシュし、削除に失敗すると、他の 99 台のサーバーは通知を待機し続け、それで終わりになります。 。 。

このとき、一時ノードを使用する必要があります。前に述べたように、一時ノードの特性は、クライアントが切断されると、つまりサーバー 1 がノードを作成してハングアップすると、一時ノードが失われることです。

その後、このノードは自動的に削除され、後続のサーバーが引き続きノードを作成し、ロックを取得できるようになります。

しかし、ショック効果という点にも注意を払う必要があるかもしれません。非常に単純な例を挙げると、ハトの群れに食べ物を投げると、最終的に食べ物をつかむのは 1 羽のハトだけであっても、すべてのハトが驚いて食べ物を奪い合い、つかみ損ねたハトは...

つまり、サーバー 1 ノードに変更があった場合、残りの 99 台のサーバーに通知されますが、最終的に正常に作成されるのは 1 台のサーバーのみなので、98 台はまだ監視を待つ必要があります。この状況に対処するには、一時的なシーケンシャル ノードが必要です。

一般的な意味は、以前は 99 台のサーバーすべてが 1 つのノードをリッスンしていましたが、現在は各サーバーがその前にあるノードをリッスンするということです。

100 台のサーバーが同時にリクエストを送信すると仮定すると、/zkjjj ノードの下に、/zkjjj/000000001、/zkjjj/000000002、そして /zkjjj/000000100 までの 100 個の一時的な連続ノードが作成されます。この数値は、ロックを取得する順序を設定することと同じです。

ノード 001 が処理されて削除されると、002 は通知を受け取り、ロックを取得して実行を開始し、実行が完了したらノードを削除して 003 に通知する、というように動作します。

<<:  分散ストレージアーキテクチャを1つの記事で理解するには、この分析を収集する価値があります

>>:  JVMクラスローディングサブシステムの解毒について話しましょう

推薦する

地方中小ネット企業の変革の道:無力で困難だらけ

インターネットの発展により、インターネット企業が急増しました。地方には、主にウェブサイトの構築やウェ...

Webmaster.com からの毎日のレポート: 多くのリベート ウェブサイトが崩壊し、JD.com は再び上級幹部を失った

1. 30近くのリベートサイトが次々と崩壊:電子商取引がねずみ講に変貌太平洋直購ネットワークが河南省...

dotvps - 3g メモリ/50g ハードディスク/1000g トラフィック/4 データセンター/月額 7 ドル

dotvps は、3G メモリ、月額 7 ドル、オプションのデータ センター 4 つ、openvz ...

ソフトコピーライティングを簡単に完成させるには、これら5つのことをうまく行う必要があります。

今はインターネットの時代です。インターネットマーケティングは企業に徐々に認知されてきました。インター...

中国のゲームで外国産ネギを収穫する正しい方法

2019年8月1日、世界的なデジタルエンターテインメントイベントChinaJoyの前日。テンセントア...

地域不動産ウェブサイトの成功に必要な条件の簡単な分析

ローカルウェブサイトは、宣伝しやすく、比較的集中した視聴者を持ち、比較的操作しやすいため、多くの草の...

入札はビジネスの成功への架け橋です

1. 入札のメリット1. すぐに結果が得られます。 入札とカタログ先行はネットワークで最も効率的です...

ウェブマスターがBaidu K-stationを心配する理由の分析

K-station事件を経験した後、ほとんどのウェブマスターはBaiduの自然なランキングに疑問を抱...

SEO はインターネット マーケティング手法の 1 つにすぎません。あまり偏りすぎないようにしてください。

ウェブマスターとして、私たちは SEOER が毎日行うべきことを行っています。つまり、毎日外部リンク...

クラウドコンピューティングとデータ分析を活用してビジネス開発を促進

今日のダイナミックなビジネス環境において、組織は効率性、俊敏性、価値を高める革新的な方法を常に模索し...

「2018年モバイルゲーム広告レポート」:広告は徐々に多くのゲーム会社によって真剣に受け止められつつある

ユーザーが 1 日に 4 時間以上モバイル画面を見つめている時間のうち、12% の時間はゲームに費や...

主流の検索エンジンの原則

今日は検索エンジンの原理を紹介します。まずは写真を見てみましょう…次に、階層ごとに説明します。 1....

ドラマ動画サイトの高額価格の裏側:頻繁にお金を使うが儲からない

優酷のCEO顧永健氏(左)と土豆のCEO王維氏は昨年は同盟者だったが、独占放送権をめぐって今年は「敵...

desivps が losangelesvps.com を買収

創業から3年未満のアメリカのVPS販売業者losangelesvps.comが、www.desivp...