[大企業からの面接質問] 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 管理のリーダーに

推薦する

Google の公式 SEO 推奨事項

Google は最近、SEO に過度に取り組んでいる多数のウェブサイトを罰しており、その結果、収益を...

ウェブサイト製品の口コミマーケティングを実施する方法

いわゆる口コミマーケティングは口コミです。例えば、私が電化製品を販売するタオバオストアを持っている場...

AWS Lambda の紹介

AWS Lambda を使用すると、サーバーをプロビジョニングしたり管理したりせずにコードを実行でき...

3年間の精力的な努力の末、7月22日にウェブサイトが構築されましたが、すべてが失われました。

今日、目が覚めて自分のウェブサイトを開いたとき、ビルから飛び降りたい気分でした。まず、Baidu 検...

VMwareは持続可能なイノベーションを推進し続けます

暗号通貨、機械学習、ビッグデータなどの計算集約型テクノロジーの急速な導入により、データセンターの電力...

profitserver: スペインのデータセンターの VPS の簡単なレビュー

Profitserver は常に無制限トラフィックの VPS サービスに重点を置いてきました。コア ...

boltvm-$2.25/1g メモリ/100g ハードディスク/1T トラフィック/G ポート/ロサンゼルス

DediCube LLC (サーバーレンタルおよびホスティング) 傘下の VPS ブランドである B...

ホストラウンド: $30/I3-2100/4GB メモリ/500GB ハードドライブ/50TB トラフィック/リースウェブ データセンター/オランダ

Hostround はアメリカのホスティング会社です。主な業務はサーバーのレンタルですが、仮想ホステ...

通信会社は最近、cn2 gia 市場を是正しています。こちらは、米国の cn2 gia 回線をまだ販売している VPS 販売業者のリストです。

道端のコミュニティからの噂:中国電信はcn2 giaを違法に販売する者を処罰するだろうあるいは市場を...

クライアントの非現実的な SEO の夢についての簡単な議論

個別に注文を受ける方は、さまざまなお客様に出会うことになります。こうしたお客様とどのように接していま...

新しいサイトの急速なランキングに影響を与える最大の要因は何ですか?

新しいウェブサイトが最短時間でランキングのメリットを最大化する方法こそが、すべての SEO 担当者が...

クラウド分析とリモート監視が自動化の次の大きなトレンドとなる理由

企業は俊敏性を高め、ビジネス継続性のためにクラウドとリモート監視に重点を置く必要があります。テクノロ...

リースウェブ - 1g メモリ KVM/40g ハードディスク/500g トラフィック/月額 7 ドル

リースウェブは、1997 年に設立された、歴史のある有名なインターネット アプリケーション プロバイ...

360 エンタープライズ セキュリティ: ネットワークをより安全に

[51CTO.com からのオリジナル記事] 360 Enterprise Security Gro...

24quanの業務停止の背景:投資熱の後に損失を止めたいという衝動

1か月の交渉の後、投資家と創業チームの間の対立は再び激化し、生き残るためにベンチャーキャピタルに依存...