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

推薦する

中小企業はまだSEO採用を行っていますか?プロセス全体をカバーするトップSEOソリューション

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています昨今、オン...

justhostはどうですか?イタリアのVPSの簡単なレビュー

justhostはどうですか? JustHost Italy VPS はいかがでしょうか? Just...

米国でトップクラスのクラウドサーバーおよびVPSプロバイダーであるDigitalocean

世界のクラウド サーバー市場における最初の破壊者は誰かを知りたいなら、間違いなく DigitalOc...

ホームファニシング電子商取引Qijia.comがオフラインで反撃:Oriental Homeの19店舗を買収

北京から記者の唐勲芳が報告します電子商取引はオフラインで「反撃」し始めた。 1月10日、本紙記者はQ...

データ分析: Baidu は K-station を通じてユーザー エクスペリエンスを向上できるか?

Baidu は、ユーザー エクスペリエンスを向上させるためだと主張して、大規模なサイト禁止を実施して...

古いサイトのランキングがジェットコースターのように変動する本当の理由を分析する

みなさんこんにちは。私はShi Touです。企業のウェブサイトを最適化する過程では、常にいくつかの厄...

アマゾン中国が2015年の書籍ランキングを発表

12月10日、アマゾン中国は北京で2015年の年間書籍ランキングを発表した。これには「年間書籍売上ラ...

Amazon Web ServicesがAWS Outpostsを発表

[51CTO.com クイック翻訳] Amazon の Amazon Web Services (A...

検索エンジン最適化 (I): フォーラム署名値分析

ウェブサイトの外部リンクを最適化する方法は無数にありますが、最も簡単な最適化方法は「フォーラム署名」...

クラウド セキュリティについて尋ねるべき 9 つの重要な質問

1. クラウド環境のコンプライアンスはどの程度ですか?クラウドで運用している企業組織には、規制やセキ...

5月のWeChatミニプログラム調査レポート:トップ100ミニプログラムに40個のミニゲームが選出されました!

昨日、アラジンミニプログラム統計プラットフォームは「2018年5月のWeChatミニプログラムトップ...

百度、自社コンテンツをクロールしたとして奇虎360を提訴、1億人民元の損害賠償請求

百度は、奇虎360が自社のウェブサイトのコンテンツをコピーしたことは不正競争に当たるとして、北京市第...

2022年にクラウドコンピューティングインフラに対するサイバー犯罪の脅威が増加

サイバーセキュリティの世界では、サイバー脅威と戦うことは、終わりのない多次元のモグラ叩きゲームをプレ...