誰もが推奨する Redis 分散ロックは本当に万全なのでしょうか?

誰もが推奨する Redis 分散ロックは本当に万全なのでしょうか?

単一インスタンス JVM には、アクセス制御用の synchronized キーワード、volatile キーワード、ReentrantLock などの一般的なメソッドなど、同時実行性の問題に対処するための一般的なメソッドが多数あります。ただし、分散環境では、上記の方法を使用して、JVM 間のシナリオにおける同時実行の問題を処理することはできません。ビジネス シナリオで分散環境での同時実行の問題を処理する必要がある場合は、分散ロックを使用して実装する必要があります。

[[268881]]

分散ロックとは、分散展開環境でロック メカニズムを使用して、複数のクライアントが共有リソースに相互に排他的にアクセスできるようにすることです。

現在、より一般的な分散ロック実装ソリューションは次のとおりです。

  • MySQLなどのデータベースに基づく
  • Redisなどのキャッシュに基づく
  • Zookeeper、etcd などに基づいています。

ここでは、キャッシュ(Re​​dis)を使用して分散ロックを実装する方法を紹介します。

Redis を使用して分散ロックを実装する最も簡単なソリューションは、SETNX コマンドを使用することです。 SETNX (SET if Not eXist) の使用方法は次のとおりです: SETNX キー値。キー key が存在しない場合にのみ、キー key の値が value に設定されます。キー key が存在する場合、SETNX は何もアクションを実行しません。 SETNX は設定が成功した場合は を返し、失敗した場合は 0 を返します。ロックを取得したい場合は、SETNX を使用してロックを取得するだけです。ロックを解除したい場合は、DEL コマンドを使用して対応するキーを削除します。

上記の解決策には致命的な問題があります。つまり、スレッドがロックを取得した後、何らかの異常な要因 (クラッシュなど) によりロック解除操作を正常に実行できず、ロックが解放されなくなります。これを実行するには、このロックにタイムアウトを追加します。 ***時間は、Redis の EXPIRE コマンド (EXPIRE キーの秒数) を思い出させます。ただし、EXPIRE と SETNX は 2 つの操作であり、2 つの操作の間に例外が発生する可能性があるため、ここでは分散ロックを実装するために EXPIRE を使用することはできません。そのため、期待される結果は得られません。例は次のとおりです。

  1. // ステップ 1
  2. SETNXキー
  3. // ここで(STEP1とSTEP2の間)プログラムが突然クラッシュすると、有効期限を設定できず、ロックが解除されない可能性があります。
  4. // ステップ 2
  5. EXPIREキーの有効期限

これに対する正しいアプローチは、「SET キー値 [EX 秒] [PX ミリ秒] [NX|XX]」コマンドを使用することです。

Redis バージョン 2.6.12 以降では、SET コマンドの動作は一連のパラメータによって変更できます。

  • EX seconds: キーの有効期限を seconds 秒に設定します。 SET key value EX seconds を実行した場合の効果は、SETEX key seconds value を実行した場合と同じです。
  • PX ミリ秒: キーの有効期限をミリ秒に設定します。 SET キー値 PX ミリ秒を実行した場合の効果は、PSETEX キー ミリ秒値を実行した場合の効果と同じです。
  • NX: キーが存在しない場合にのみ設定します。 SET キー値 NX を実行した場合の効果は、 SETNX キー値 を実行した場合と同じです。
  • XX: キーがすでに存在する場合にのみ設定します。

たとえば、分散ロックを作成し、有効期限を 10 秒に設定するには、次のコマンドを実行します。

  1. SETロックキー ロック値 EX 10 NX
  2. または
  3. SET lockKey lockValue PX 10000 NX

EX と PX を同時に使用することはできません。同時に使用すると、ERR 構文エラーというエラーが報告されます。

ロックを解除するときは、引き続き DEL コマンドを使用してロックを解除します。

修正された計画は素晴らしいように見えますが、まだ問題があります。スレッド A がロックを取得し、有効期限を 10 秒に設定し、ビジネス ロジックの実行に 15 秒かかるとします。この時点で、スレッド A によって取得されたロックは、Redis の有効期限メカニズムによってすでに自動的に解放されています。スレッド A がロックを取得してから 10 秒が経過すると、他のスレッドによってロックが取得されている可能性があります。スレッド A がビジネス ロジックの実行を終了し、ロック解除 (DEL キー) の準備を行うと、他のスレッドが取得したロックが削除される可能性があります。

したがって、最善の方法は、ロックを解除するときに、ロックが自分のものであるかどうかを確認することです。キーを設定するときに、値を一意の値 uniqueValue に設定できます (ランダムな値、UUID、またはマシン番号 + スレッド番号の組み合わせ、署名など)。ロックを解除する、つまりキーを削除するときは、まずキーに対応する値が以前に設定された値と等しいかどうかを判断します。等しい場合は、キーを削除できます。疑似コードの例は次のとおりです。

  1. uniqueKey == GET(キー)の場合{
  2. DELキー 
  3. }

ここで問題となるのは、GET と DEL が別々の操作であり、GET の実行と DEL の実行の間のギャップで例外が発生する可能性があることです。ロック解除コードがアトミックであることを保証する必要があるだけであれば、問題は解決できます。ここでは、Lua スクリプトという新しい方法を紹介します。例は次のとおりです。

  1. redis.call( "get" ,KEYS[1]) == ARGV[1]の場合 
  2. redis.call( "del" ,KEYS[1])を返す
  3. それ以外 
  4. 0を返す
  5. 終わり 

ARGV[1]はキー設定時に指定された一意の値を表します。

Lua スクリプトのアトミック性のため、Redis がスクリプトを実行している場合、他のクライアントからのコマンドは Lua スクリプトが完了するまで待機してから実行する必要があります。

次に、Jedis を使用して、次のようにロックの取得とロック解除の実装を示します。

  1. パブリックブールロック(文字列ロックキー、文字列一意の値、 int秒){
  2. SetParams パラメータ = 新しい SetParams();
  3. params.nx().ex(秒);
  4. 文字列結果 = jedis.set (lockKey、uniqueValue、params);
  5. if ( "OK" .equals(結果)) {
  6. 戻る 真実;
  7. }
  8. 戻る 間違い;
  9. }
  10. パブリックブールロック解除(文字列ロックキー、文字列一意の値){
  11. 文字列スクリプト = "if redis.call('get', KEYS[1]) == ARGV[1] " +
  12. 「その後、redis.call('del', KEYS[1]) を返し、そうでない場合は 0 を返して終了します」 ;
  13. オブジェクト結果 = jedis.eval(script,
  14. コレクション.シングルトンリスト(ロックキー)、
  15. Collections.singletonList(uniqueValue));
  16. (結果が1に等しい場合){
  17. 戻る 真実;
  18. }
  19. 戻る 間違い;
  20. }

これは絶対確実ですか?明らかに違います!

表面的には、この方法は機能しているように見えますが、ここには問題があります。システム アーキテクチャに単一障害点があるのです。 Redis マスターノードがダウンしたらどうなりますか? 「スレーブノードを追加してください」と言う人もいるかもしれません。マスターがダウンしたらスレーブを使用してください。

しかし実際には、Redis レプリケーションは非同期であるため、このソリューションは明らかに実現可能ではありません。例えば:

  1. スレッド A はマスター ノードのロックを取得します。
  2. A によって作成されたキーをスレーブに書き込む前に、マスター ノードがクラッシュしました。
  3. スレーブノードがマスターノードになります。
  4. スレッド B も、スレッド A が保持しているのと同じロックを取得します。 (元のスレーブはロックを保持しているAに関する情報を持っていないためです)

もちろん、この解決策はいくつかのシナリオでは適切です。たとえば、ビジネス モデルで同時ロック保持が許可されている場合は、このソリューションを使用できます。

たとえば、サービスには A と B という 2 つのサービス インスタンスがあります。最初に、A はロックを取得してリソースを操作します (この操作はリソースを大量に消費すると想定できます)。一方、B はロックを取得せず、操作も実行しません。このとき、B は A のホットスタンバイとみなすことができます。A が異常な動作をした場合、B を「正常化」することができます。 Redis マスターがクラッシュするなど、ロックが異常な場合、B はロックを保持し、同時にリソースを操作する可能性があります。操作の結果がべき等である場合(またはその他の状況)は、このソリューションも使用できます。ここで分散ロックを導入すると、通常の状況下での繰り返し計算やリソースの浪費をサービスが回避できるようになります。

この状況に対処するために、Antriez は Redlock アルゴリズムを提案しました。 Redlock アルゴリズムの主なアイデアは、完全に独立した N 個の Redis マスター ノードがあると仮定することです。前のソリューションを使用して、ロックを取得し、前の単一の Redis マスター ノードのロックを解除できます。妥当な範囲内でロックを取得できる場合、または全体で N/2+1 個のロックを取得できる場合は、ロックが正常に取得されたと見なすことができます。それ以外の場合は、ロックは取得されていません (クォーラム モデルと比較できます)。 Redlock の原理は理解しやすいですが、内部実装の詳細は非常に複雑であり、多くの要素を考慮する必要があります。

Redlock アルゴリズムは「万能薬」ではありません。やや厳しい条件に加え、アルゴリズム自体も疑問視されている。 Redis 分散ロックのセキュリティに関しては、分散システムの専門家 Martin Kleppmann 氏と Redis の作者 antirez 氏の間で議論がありました。

<<:  選ばれたソリューションが生まれ、その背後にある3つの価値が説明される

>>:  クラウドコンピューティング技術が大企業に与える影響

推薦する

これら6つの側面がうまく行われないと、訪問者を「怖がらせて」しまうのは簡単です。

ウェブサイトを構築する目的は、訪問者を引き付け、維持することです。ウェブサイトが訪問者の支持を得たい...

2019年の展望: コンテナクラウド戦争が激化、フルスタッククラウドが一般的なトレンドに

[51CTO.com からのオリジナル記事] クラウド コンピューティング テクノロジーに関しては、...

xfusesolutions-$3.99/2IP/256m メモリ/60g ハードディスク/500g トラフィック/Phoenix

2009 年に設立された VPS 販売業者の xfusesolutions は、フェニックス データ...

今後注目すべき6種類のSaaSアプリケーション

企業にとってのインターネットの重要性については、詳しく説明する必要はありません。企業はすでに「情報化...

大企業におけるSEOの課題

大企業や中小企業の Web サイトで SEO を行う際に、通常どのような課題に直面するでしょうか。た...

Weiboマーケティングを行うには?この記事を読んでみてください

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスファン経済の時代では、W...

Google の中国ウェブマスター向けチュートリアルにおけるリンク構造の重要性についての簡単な説明

コアヒント: .リンク アーキテクチャは Web サイト計画の重要な部分であり、Web サイトが検索...

Weiboマーケティングについて知っておくべきこと

中国市場を振り返ってみると、光り輝く星、Weibo マーケティングを見つけるのは難しくありません。過...

クラウドコンピューティングの大きな障害

最近、「クラウド」についてよく話題になっています。技術の急速な発展に伴い、クラウド技術は拡大し続けて...

edgevirt: TIKTOK/Netflix のロックを解除、月額 2.25 ドル、1G メモリ/1 コア/25g SSD/5T トラフィック/10Gbps 帯域幅

edgevirtは現在、主にエクニクスのマイアミデータセンターでVPSサービスを提供しています。評価...

簡単な分析: PRの価値は決して無視できない

PR 値は、Google 検索エンジンの創設者であるラリー ペイジに由来しています。この人物を知らな...

Oracle: クラウドの将来に関する 10 の予測と 4 つの展望

2019年が静かに到来しました。 2018 年を振り返ると、デジタル変革は間違いなくエンタープライズ...

MongoDBの株価は320億ドルを超え、最も価値のあるオープンソースソフトウェア企業となった。

[[422308]]要点: MongoDBの株価が急騰しており、その市場価値はIBMが2019年にR...

ウェブサイトの最適化前のSWOT分析がウェブサイトの成功または失敗を決定します

典型的なビジネス スクールのコースは、ビジネスやプロジェクトが直面する強み、弱み、機会、脅威を特定す...

伝統メディアによる今日頭条ボイコットはどんなシグナルを発しているのだろうか?

6月3日、「データマイニングに基づくパーソナライズされた情報推奨エンジン」を提供するアプリ「今日頭条...