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

推薦する

dmit: ロサンゼルス cn2 gia 超高セキュリティ VPS、1Gbps 帯域幅または 200Mbps 無制限トラフィック

香港の VPS に注力してきた Dmit 社が、新製品を追加しました。ロサンゼルス CN2 GIA ...

注: 年末最後の日、最後の乾物、[サイバーマンデー]

新年はあっという間に終わります。新年に向けて準備して、ドメイン名、仮想ホスト、VPS、サーバーを準備...

Baiduの「ダーリン」を解決する方法

Baidu の最近の動きは、歴史上最大規模のものと言えるでしょう。多くのウェブマスターが深刻な被害を...

SEOに影響を与える要因についての簡単な説明

ホストスペースは、ウェブサイト運営の基本的なプラットフォームであり、ウェブサイトページの表示速度やウ...

クラウド コンピューティングの支出を管理する 7 つの方法

調査会社カナリスの調査によると、クラウドコンピューティングサービスへの世界の支出は2020年第2四半...

Dockerの基本原理とソースコード分析 Dockerアーキテクチャ

[[279395]]序文Docker入門Docker は、Docker が開発した軽量仮想化テクノロ...

製造業におけるエッジコンピューティング: 業務の合理化と効率性の向上

エッジ コンピューティングは製造業界において革命的なテクノロジーとなり、企業の運営方法を変え、プロセ...

onetechcloud: US cn2 gia vps、58元/月、1.4Tトラフィック/月、KVM/1Gメモリ/1コア/15g SSD

onetechcloudのUS cn2 gia vps特別イベントでは、月払いで20%割引、四半期払...

細部にこだわって勝つフォーラム: エネルギーを分散させすぎない

「フォーカスとセグメンテーションで勝つ」円卓会議(写真はテンセントテクノロジー撮影)テンセントテクノ...

8月ももうすぐ終わりますが、他に見る価値のあるもの(退屈なもの)はありますか?

8月以来、Host Catは37の記事を公開しました(この記事を含む)。ここでは、家庭内の兄弟が注目...

hostodo-15 USD/年/KVM/512MB メモリ/クアドラネット データ センター/ロサンゼルス

hostodo.com の格安 VPS が再入荷し始めました。Quadranet のロサンゼルス デ...

ウェブサイトのデザインが失敗する原因とは?ユーザーエクスペリエンスの「アンチパターン」について簡単に説明します

ウェブサイトのユーザーとして、ウェブサイトを使用する際に時々煩わしい点があることに気付くかもしれませ...

Apple、新型iPhone SEの発売によりiPhone 8を店頭から撤去

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービス昨夜、新型iPhone ...

百度のウェブサイトインデックスの急激な低下に関する考察

周知のとおり、6月22日と6月28日の最近の出来事はインターネット上で広く伝えられ、多くのウェブマス...

分散アーキテクチャにおける「負荷分散」について 1 つの記事で学ぶ

ウェブサイトの初期の頃は、集中的なサービスを提供するために一般的に 1 台のマシンを使用していました...