Redisson 分散ロック ソースコード フェアロック ロック

Redisson 分散ロック ソースコード フェアロック ロック

[[408379]]

序文

デフォルトのロックロジックは不公平です。

ロックが失敗すると、スレッドは while ループに入り、ロックの取得を試行し続けます。このとき、複数のスレッドが競合することになります。つまり、最初にそれを獲得した人がそれを所有することになります。

Redisson は、次のように使用できる公平なロック メカニズムを提供します。

  1. RLock fairLock = redisson.getFairLock( "anyLock" );
  2. // 最も一般的な使用法
  3. ロックをロックします。

公平ロックがどのように実装されるかを見てみましょう。

1フェアロック

これまでの記事を読んだ後は、すでにこのメソッドに精通しており、ソース コード メソッド RedissonFairLock#tryLockInnerAsync を直接見つけることができると思います。

わあ、これは膨大なコードなので、スクリーンショットですべてをキャプチャすることはできません。そのため、Lua スクリプトを直接分析してみましょう。

PS: Lua は理解できませんが、これらの if else の山はおそらく理解できるでしょう。

デバッグで command == RedisCommands.EVAL_LONG が見つかったため、次の部分を直接確認します。

長すぎて「いい人」って何回も言ってしまいました!

まずパラメータが何であるかを見てみましょう。

  • KEYS[1]: ロック名、anyLock;
  • KEYS[2]: ロック待機キュー、redisson_lock_queue:{anyLock};
  • KEYS[3]: 待機キュー内のスレッドロック時間のセット、redisson_lock_timeout:{anyLock}。ロックタイムスタンプに従ってセットに格納されます。
  • ARGV[1]: ロックタイムアウト30000;
  • ARGV[2]: UUID:スレッドIDの組み合わせa3da2c83-b084-425c-a70f-5d9a08b37f31:1;
  • ARGV[3]: threadWaitTimeのデフォルトは300000です。
  • ARGV[4]: currentTime 現在のタイムスタンプ。

ロック キューとセットは中括弧で囲まれた文字列です。 {XXXX} は、このキーがスロット位置を計算するために XXXX のみを使用することを意味します。

2Luaスクリプト解析

上記の Lua スクリプトはいくつかの部分に分かれています。上記のコードの実行をさまざまな角度から見てみましょう。

最初のロック(スレッド1)

最初の部分では、ロックするのは初めてなので、待機キューは空であり、ループは直接飛び出します。実行のこの部分は終了しました。

パート II:

  1. ロックが存在しない、待機キューが空である、またはキューの先頭が現在のスレッドであり、両方の条件が満たされている場合、内部ロジックに入ります。
  2. 現在のスレッドを待機キューおよびタイムアウトコレクションから削除します。この時点では、待機キューとタイムアウトコレクションは空であり、操作は必要ありません。
  3. キュー内のすべての待機スレッドのタイムアウトを短縮します。何もする必要はありません。
  4. ロックしてタイムアウトを設定します。

ここで実行したら戻ります。なので、今のところ以降の部分は読みません。

次の 2 つのコマンドと同等です (Lua スクリプト全体がアトミックです)。

  1. > hset anyLock a3da2c83-b084-425c-a70f-5d9a08b37f31:1 1
  2. > pexpire anyLock 30000

スレッド2ロック

Thread1 がロックを完了すると、Thread2 がロックを開始します。

Thread2 は、このインスタンスの別のスレッド、または別のインスタンスのスレッドにすることができます。

最初の部分では、ロックは Thread1 によって占有されていますが、待機キューは空なので、ループは直接飛び出します。

2 番目の部分では、ロックが存在するので、スキップします。

3 番目の部分は、スレッドがロックを保持しているかどうかです。そうでない場合は、直接スキップしてください。

4 番目の部分は、スレッドが待機キューにあるかどうかです。Thread2 はそれをロックし、そうでない場合は直接スキップされます。

スレッド2はここで終了します:

  1. スレッド待機キューから最後のスレッドを取得します redisson_lock_queue:{anyLock};
  2. 待機キューが空なので、現在のロック ttl anyLock の残り時間を直接取得します。
  3. アセンブリ タイムアウト timeout = ttl + 300000 + 現在のタイムスタンプ、300000 はデフォルト 60000*5 です。
  4. zadd を使用して、Thread2 を待機中のスレッドの順序付きセットに追加し、rpush を使用して Thread2 を待機中のキューに戻します。

zadd KEYS[3] タイムアウトARGV[2]

ここでは、zadd コマンドを使用して、redisson_lock_timeout:{anyLock}、タイムアウト タイムスタンプ (1624612689520)、およびスレッド (UUID2:Thread2) を配置します。

タイムアウト タイムスタンプは、順序付けられたセット内でソートするためのスコアとして使用され、ロックの順序を示します。

スレッド3ロック

スレッド 1 がロックを保持し、スレッド 2 が待機し、その後スレッド 3 が来ます。

firstThreadId2を取得します。この時点で、キューには UUID2:Thread2 のスレッドがあります。

firstThreadId2 のスコア (タイムアウト タイムスタンプ) が現在のタイムスタンプより小さいかどうかを判断します。

タイムアウト以下の場合は、firstThreadId2 を削除します。

より大きい場合は、その後の判定に入ります。

2番目、3番目、4番目の部分は要件を満たしていません。

Thread3 もここで終了します:

  1. スレッド待機キューから最後のスレッドを取得します redisson_lock_queue:{anyLock};
  2. 最後のスレッドが存在し、それがそれ自身ではない場合は、ttl = lastThreadId タイムアウト タイムスタンプ - 現在のタイムスタンプとなり、最後のスレッドがタイムアウトするまでの時間を確認します。
  3. アセンブリ タイムアウト時間 = ttl + 300000 + 現在のタイムスタンプ。 300000 は 60000*5 のデフォルト値です。最後のスレッドのタイムアウト(Thread3 のタイムアウト タイムスタンプ)に 300000 と現在のタイムスタンプを追加します。
  4. zadd を使用して Thread3 を待機スレッド順序セットに追加し、rpush を使用して Thread3 を待機キューに戻します。

3 まとめ

この記事では主に、多くの Redis 操作に関係するフェア ロックのロック ロジックについてまとめます。以下に簡単な要約を示します。

  1. Redis ハッシュ データ構造: 現在のロックを格納します。 Redis キーはロック、ハッシュ フィールドはロック スレッド、ハッシュ値は再入回数です。
  2. Redis リスト データ構造: スレッド待機キューとして機能します。新しい待機スレッドは、rpush コマンドを使用してキューの右側に配置されます。
  3. Redis ソート セット オーダー セット データ構造: 待機中のスレッドの順序を格納し、スコアは待機中のスレッドのタイムアウト タイムスタンプとして使用されます。

理解しておく必要があるのは、追加の待機キューと順序付きセットがここに追加されるということです。

この記事はWeChatの公開アカウント「Programmer Xiaohang」から転載したもので、以下のQRコードからフォローできます。この記事を転載する場合は、プログラマーXiaohangの公式アカウントまでご連絡ください。

<<:  分散データベース システムのフォールト トレランス - 100% の成功率、タイムアウト、パフォーマンス

>>:  FONEは2021年中国消費財業界CIOカンファレンスに参加し、ビジネスと金融のデジタル変革について議論しました。

推薦する

コンバージョン率を上げる方法が分からないですか?ゲームをしましょう!

最近、とても面白いことが起きています。そういうゲームがあるんです。相手がそのゲームをやっているとわか...

WeChatは後戻りできない閉ざされた道に向かっている。それは収益化のためか?

鉄閣は春節に帰省した際、田舎から都市への新年の挨拶メッセージが明らかにテキストメッセージからWeCh...

Baidu に降格された動画収集サイトを復活させる方法

みなさんこんにちは。私は飛虎映画ウェブサイトの所有者です。タイトルの通り、私の映画コレクションウェブ...

自然観光ネットワークの発展の道:ネットワークユーザーの信頼を獲得

観光ウェブサイトは、文化観光ウェブサイトと自然観光スポットウェブサイトに分かれています。現在の観光ス...

Kubernetes C# クライアント ライブラリを使用するにはどうすればよいでしょうか?

[51CTO.com クイック翻訳] Kubernetes の使用は必ずしも簡単ではありません。クラ...

またまた受賞です! | H3CがGNTCカンファレンスで輝き、インテリジェントネットワークの革新をリード

10月22日から24日まで、国家次世代インターネットエンジニアリングセンターが主催し、南京江北新区...

Xiong Zhanghao: ブログ最適化のための SEO テクニックは何ですか?

月収10万元の起業の夢を実現するミニプログラム起業支援プラン新しいメディアプラットフォームの発展に伴...

dogyun: 庚子年を迎え、VPSは香港CN2、ドイツCN2、日本ソフトバンクを含め30%オフ、IP切り替えはわずか10元

Dogyun はネズミ年を歓迎し、プロモーションを実施しています: 1. Dynamic Cloud...

世界のデジタルインフラの将来に関するトップ10の予測

[[438392]]調査会社 IDC は、回復力と信頼性の問題、データ主導の運用の複雑さ、ビジネス成...

忘れられがちなSEOのヒント: キーワード調査

みなさんこんにちは。SEOを行う際、キーワードリサーチに重点が置かれます。多くの友人がこの点で良い仕...

ファーウェイのクラウドネイティブ分散データベースと高性能データベース技術の公開

クラウド時代の発展とともに、データベースの物語は続きます。 Oracle の商用バージョンであれ、M...

bandwagonhost-512Mメモリ ロサンゼルスデータセンター VPS テスト

Hostcat は、bandwagonhost に関するプロモーション記事を公開しました: band...

ウェブサイトの最適化効果の向上に関する簡単な説明

ウェブサイトの最適化に取り組んでいる SEO 担当者は、ウェブサイトの効果を最大限に高めたいと考えて...

電子商取引のプロモーションは登録が義務化され、来年は価格競争が緩和される可能性がある

オンライン情報への監視強化を求める世論を背景に、電子商取引サイトのプロモーション登録も関係部門の議題...

中秋節ブランドマーケティング企画プログラム!

一般人にとって、中秋節は家族が集まる良い日ですが、マーケティング担当者にとっては頭を悩ませ、頭がゾク...