[大企業からの面接質問] Redis では分散ロックはどのように実装されていますか?

[大企業からの面接質問] Redis では分散ロックはどのように実装されていますか?

分散ロックを実装する一般的な方法は 3 つあります。

  1. データベースの楽観的ロック。
  2. Redis に基づく分散ロック。
  3. ZooKeeper に基づく分散ロック。

現地面接のテストポイントは、Redis の使用に精通しているかどうかです。 Redis で分散ロックを実装する方法。

要点

Redisで分散ロックを実装するには、以下の条件を満たす必要があります。

相互排他性

  • 一度にロックを保持できるのは 1 つのクライアントのみです。

デッドロックなし

  • ロックを保持している間にクライアントがクラッシュし、ロックを積極的に解除しなかった場合でも、他のクライアントが後でロックをロックすることができます。

フォールトトレランス

  • ほとんどの Redis ノードが正常に実行されている限り、クライアントはロックおよびロック解除を行うことができます。

成し遂げる

set key value px milliseconds nx コマンドを直接使用してデバイスをロックし、Lua スクリプトを使用してロックを解除することができます。

  1. //ロックを取得します (unique_value は UUID などになります)  
  2. リソース名と一意の値を設定する NX PX 30000  
  3. //ロックを解除します(Lua スクリプトでは、ロックの誤解を防ぐために必ず値を比較してください)  
  4. redis.call("get",KEYS[1]) == ARGV[1]の場合 
  5. redis.call("del",KEYS[1]) を返す
  6.  それ以外 
  7. 0を返す 
  8. 終わり

コードの説明

  • set コマンドでは、setnx + expire ではなく、set key value px milliseconds nx を使用する必要があります。アトミック性を保証するには、コマンドを 2 回実行する必要があります。
  • 値は一意である必要があります。 UUID.randomUUID().toString() メソッドを使用して生成できます。これは、どのリクエストがロックを追加したかを識別するために使用され、ロックを解除するための基礎を得ることができます。
  • ロックの誤解を防ぐために、ロックを解除するときに値を確認します。
  • ロックの解放には複数の Redis 操作 (eval コマンドのアトミック性を使用して Lua スクリプトを実行する) が含まれるため、Check And Set モデルでの同時実行の問題を回避するには Lua スクリプトを使用します。

ロックコード解析

まず、set() は NX パラメータを追加して、キーがすでに存在する場合は関数が正常に呼び出されないようにします。つまり、相互排他性を満たすために、1 つのクライアントだけがロックを保持できます。次に、ロックに有効期限を設定しているため、ロック保持者が後でクラッシュしてロックを解除しなくても、有効期限に達するとロックは自動的にロック解除され(つまり、キーが削除され)、デッドロックは発生しません。最後に、ロックがどのリクエストに属しているかを識別するために requestId に値を割り当てるため、クライアントがロックを解除するときに、同じクライアントであるかどうかを確認できます。

コード分​​析のロック解除

Luaコードをjedis.eval()メソッドに渡し、パラメータKEYS[1]をlockKeyに、ARGV[1]をrequestIdに割り当てます。実行中、ロックに対応する値が最初に取得され、それが requestId と等しいかどうかが確認されます。等しい場合は、ロックが解除されます(キーが削除されます)。

リスク

ロックに対応するキーを格納しているノードがクラッシュすると、ロックが失われ、複数のクライアントがロックを保持することになり、リソースの排他的使用ができなくなるリスクがあります。

  1. クライアントAはマスターからロックを取得する
  2. マスターがスレーブにロックを同期する前に、マスターがクラッシュします (Redis のマスターとスレーブの同期は通常非同期です)。

マスタースレーブ切り替え、スレーブノードがマスターノードに昇格される

3. クライアント B は、クライアント A がすでに取得している同じリソースに対して別のロックを取得します。これにより、複数のスレッドが同時にロックを取得することになります。

レッドロックアルゴリズムが登場

このシナリオでは、5 つの Redis マスター インスタンスを持つ Redis クラスターがあることを前提としています。次に、ロックを取得するには次の手順を実行します。

  1. 現在のタイムスタンプをミリ秒単位で取得します。
  2. 上記と同様に、各マスターノードに順番にロックを作成し、有効期限を短く(通常は数十ミリ秒)してみます。
  3. 大多数のノードでロックを確立するようにしてください。たとえば、5 つのノードには 3 つのノード n/2 + 1 が必要です。
  4. クライアントはロックを確立するのにかかる時間を計算します。ロックを確立するのにかかる時間がタイムアウトより短い場合、ロックは正常に確立されます。
  5. ロックの作成に失敗した場合、以前に作成されたロックが順番に削除されます。
  6. 他の誰かが分散ロックを確立している限り、ロックを取得するためにポーリングを継続する必要があります。

Redis は、Redis ベースの分散ロックを実装するために、上記の 2 つの方法を公式に提供しています。詳しい説明については以下を参照してください。

https://redis.io/topics/distlock。

Redisson 実装

Redisson は、Redis をベースに実装された Java インメモリ データ グリッドです。一連の分散型 Java 共通オブジェクトを提供するだけでなく、再入可能ロック (Reentrant Lock)、公平ロック (Fair Lock)、インターロック (MultiLock)、レッドロック (RedLock)、読み取り/書き込みロック (ReadWriteLock) などを実装し、多くの分散サービスも提供します。

Redisson は、Redis を使用する最も簡単で便利な方法を提供します。 Redisson の目的は、Redis 上のユーザーの関心の分離を促進し、ユーザーがビジネス ロジックの処理に集中できるようにすることです。

Redisson 分散再入可能ロックの使用

Redisson は、シングルポイント モード、マスター スレーブ モード、センチネル モード、クラスター モードをサポートしています。ここではシングルポイントモードを例に挙げます。

  1. // 1. 分散ロックに必要なConfigを実装するためにredissonを構築する 
  2. 設定config = new Config();  
  3. config.useSingleServer().setAddress("redis://127.0.0.1:5379").setPassword("123456").setDatabase(0);  
  4. // 2. RedissonClient を構築する 
  5. RedissonClient redissonClient = Redisson .create(config);  
  6. // 3. ロックオブジェクトのインスタンスを取得します(スレッドの順序どおりに取得されるとは限りません)  
  7. RLock rLock = redissonClient .getLock(lockKey);  
  8. 試す {  
  9. /**  
  10. * 4. ロックを取得してみる 
  11. * waitTimeout ロックの取得を試行する際の最大待機時間。この値を超えるとロック取得に失敗したとみなされます。  
  12. * リースタイム: ロック保持時間。ロックがこの時間を超えると自動的に無効になります(ロックの有効期間内に業務を処理できるように、業務処理時間よりも大きい値を設定する必要があります)  
  13. */
  14. ブール値res = rLock .tryLock((long)waitTimeout, (long)leaseTime, TimeUnit.SECONDS);  
  15. もし(res){  
  16. //ロックの取得に成功しました。ここで処理を実行します 
  17. }  
  18. } キャッチ (例外 e) {  
  19. 新しい RuntimeException("ロック取得失敗") をスローします。  
  20. }ついに{  
  21. // 何があろうと、最終的にはロックを解除しなければなりません 
  22. rLock.ロック解除();  
  23. }

ロックフローチャート

フローチャートのロック解除

RedissonLock は再入可能であり、失敗の再試行を考慮していることがわかります。ロックの最大待機時間を設定できます。無効なロックの適用を減らし、リソースの使用率を向上させるために、実装にいくつかの最適化も行われました。

RedissonLock では、ノードがクラッシュしたときにロックが失われるリスクも解決されないことに注意することが重要です。現実には、許容できないシナリオもいくつかあるため、Redisson は redlock アルゴリズムを実装する RedissonRedLock を提供しています。 RedissonRedLock は単一障害点の問題を真に解決しますが、その代償として、RedissonRedLock 用に追加の Redis 環境を構築する必要があります。

したがって、ビジネス シナリオでこのような小さなエラーの可能性を許容できる場合は、RedissonLock を使用することをお勧めします。許容できない場合は、RedissonRedLock を使用することをお勧めします。

<<:  世界はこれまで以上にクラウドネイティブを必要としている

>>:  SUSE が Rancher Labs を買収し、エンタープライズ Kubernetes 管理のリーダーに

推薦する

ウェブサイトの降格の理由とトラブルシューティング

ウェブサイトの降格といえば、6月末のBaiduアルゴリズムの大規模なアップデート(大量のスパムサイト...

ウェブサイトの最適化結果のテスト体験は、サイトのコンバージョン率の分析から始まります。

最適化が適切かどうかをどのように判断しますか?最適化が適切に行われているかどうかをどのように判断しま...

Directspace 年額 15 ドルの VPS レビュー

15ドルのVPS(標準128MメモリVZ)が目新しくなくなった頃、以前書いた安価な1Gメモリ(ope...

百度の青大根アルゴリズムが再び始動、リンクの売買行動に影響

2013年2月19日、Baiduのアルゴリズムが再び調整されました。Baiduのウェブ検索不正対策チ...

Baidu のザクロアルゴリズムは医療業界に影響を与えるか?

Baidu が最新の発表で、ザクロアルゴリズムがまもなく開始されると主張して以来、多くのウェブマスタ...

タオバオの改革戦略の実行は始まりましたか?

はじめに:皆さん、こんにちは。これらは最近起こったいくつかの状況です。私はタオバオの顧客として、タオ...

SEOerの現状と将来についての簡単な議論

Baidu の数回のメジャーアップデートにより、SEO に携わる私たちはさまざまな精神的打撃を受けた...

関連性の穴から抜け出し、SEOの視野を広げる方法

関連性を体系的に説明し、例示する記事をたくさん見てきましたが、私が言いたいのは、衣料品店は本当に衣料...

cloudcone: 米国の安価な VPS、年間 49 ドル、3G メモリ/3 コア/190G ハードディスク/6T トラフィック/1Gbps 帯域幅

安価なVPS、特に米国の安価なVPSを購入したい場合は、Cloudconeが発売した新しいHDDハー...

A5ソフト記事トレーニングを通じて今日のBaidu最適化を見る

筆者は、ソフト コピーライティングとソフト コピー マーケティングに関する第 9 回 A5 トレーニ...

IDC: 中国のパブリッククラウド市場は今後5年間で急速に成長し、複合成長率は30.9%となる見込み

IDCの最新の「中国パブリッククラウドサービス市場(2021年下半期)追跡」レポートによると、中国の...

invs: モスクワのデータセンターで最も目立たない KVM 仮想 VPS の簡単なレビュー

今年 2 月に invs 社を紹介しましたが、一般的にはあまり注目されていませんでした。1 年後の ...

王童:パーソナルブランドを構築する過程で、具体的な理論を作り、コンテンツをどのようにアウトプットしていくのでしょうか?

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスショッピングモール内の店...

推奨: vexxhost-openstack/$5/2 コア/512m メモリ/20g SSD/2T トラフィック/カナダ

Vexxhost は、7 年間運営している企業で、VPS 構成をアップグレードおよび増加し、価格を下...

Dianpingの小技、IPOへの重み付け、ホテルでの結婚式への関与

資本市場では話題に事欠かない。早期の独立上場を目指すDianpingは今日、張涛氏が率いるホテル・旅...