単一インスタンス JVM には、アクセス制御用の synchronized キーワード、volatile キーワード、ReentrantLock などの一般的なメソッドなど、同時実行性の問題に対処するための一般的なメソッドが多数あります。ただし、分散環境では、上記の方法を使用して、JVM 間のシナリオにおける同時実行の問題を処理することはできません。ビジネス シナリオで分散環境での同時実行の問題を処理する必要がある場合は、分散ロックを使用して実装する必要があります。
分散ロックとは、分散展開環境でロック メカニズムを使用して、複数のクライアントが共有リソースに相互に排他的にアクセスできるようにすることです。 現在、より一般的な分散ロック実装ソリューションは次のとおりです。
ここでは、キャッシュ(Redis)を使用して分散ロックを実装する方法を紹介します。 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 を使用することはできません。そのため、期待される結果は得られません。例は次のとおりです。
これに対する正しいアプローチは、「SET キー値 [EX 秒] [PX ミリ秒] [NX|XX]」コマンドを使用することです。 Redis バージョン 2.6.12 以降では、SET コマンドの動作は一連のパラメータによって変更できます。
たとえば、分散ロックを作成し、有効期限を 10 秒に設定するには、次のコマンドを実行します。
EX と PX を同時に使用することはできません。同時に使用すると、ERR 構文エラーというエラーが報告されます。 ロックを解除するときは、引き続き DEL コマンドを使用してロックを解除します。 修正された計画は素晴らしいように見えますが、まだ問題があります。スレッド A がロックを取得し、有効期限を 10 秒に設定し、ビジネス ロジックの実行に 15 秒かかるとします。この時点で、スレッド A によって取得されたロックは、Redis の有効期限メカニズムによってすでに自動的に解放されています。スレッド A がロックを取得してから 10 秒が経過すると、他のスレッドによってロックが取得されている可能性があります。スレッド A がビジネス ロジックの実行を終了し、ロック解除 (DEL キー) の準備を行うと、他のスレッドが取得したロックが削除される可能性があります。 したがって、最善の方法は、ロックを解除するときに、ロックが自分のものであるかどうかを確認することです。キーを設定するときに、値を一意の値 uniqueValue に設定できます (ランダムな値、UUID、またはマシン番号 + スレッド番号の組み合わせ、署名など)。ロックを解除する、つまりキーを削除するときは、まずキーに対応する値が以前に設定された値と等しいかどうかを判断します。等しい場合は、キーを削除できます。疑似コードの例は次のとおりです。
ここで問題となるのは、GET と DEL が別々の操作であり、GET の実行と DEL の実行の間のギャップで例外が発生する可能性があることです。ロック解除コードがアトミックであることを保証する必要があるだけであれば、問題は解決できます。ここでは、Lua スクリプトという新しい方法を紹介します。例は次のとおりです。
ARGV[1]はキー設定時に指定された一意の値を表します。 Lua スクリプトのアトミック性のため、Redis がスクリプトを実行している場合、他のクライアントからのコマンドは Lua スクリプトが完了するまで待機してから実行する必要があります。 次に、Jedis を使用して、次のようにロックの取得とロック解除の実装を示します。
これは絶対確実ですか?明らかに違います! 表面的には、この方法は機能しているように見えますが、ここには問題があります。システム アーキテクチャに単一障害点があるのです。 Redis マスターノードがダウンしたらどうなりますか? 「スレーブノードを追加してください」と言う人もいるかもしれません。マスターがダウンしたらスレーブを使用してください。 しかし実際には、Redis レプリケーションは非同期であるため、このソリューションは明らかに実現可能ではありません。例えば:
もちろん、この解決策はいくつかのシナリオでは適切です。たとえば、ビジネス モデルで同時ロック保持が許可されている場合は、このソリューションを使用できます。 たとえば、サービスには 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つの価値が説明される
ウェブサイトを構築する目的は、訪問者を引き付け、維持することです。ウェブサイトが訪問者の支持を得たい...
[51CTO.com からのオリジナル記事] クラウド コンピューティング テクノロジーに関しては、...
2009 年に設立された VPS 販売業者の xfusesolutions は、フェニックス データ...
企業にとってのインターネットの重要性については、詳しく説明する必要はありません。企業はすでに「情報化...
大企業や中小企業の Web サイトで SEO を行う際に、通常どのような課題に直面するでしょうか。た...
ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスファン経済の時代では、W...
コアヒント: .リンク アーキテクチャは Web サイト計画の重要な部分であり、Web サイトが検索...
中国市場を振り返ってみると、光り輝く星、Weibo マーケティングを見つけるのは難しくありません。過...
最近、「クラウド」についてよく話題になっています。技術の急速な発展に伴い、クラウド技術は拡大し続けて...
edgevirtは現在、主にエクニクスのマイアミデータセンターでVPSサービスを提供しています。評価...
PR 値は、Google 検索エンジンの創設者であるラリー ペイジに由来しています。この人物を知らな...
2019年が静かに到来しました。 2018 年を振り返ると、デジタル変革は間違いなくエンタープライズ...
[[422308]]要点: MongoDBの株価が急騰しており、その市場価値はIBMが2019年にR...
典型的なビジネス スクールのコースは、ビジネスやプロジェクトが直面する強み、弱み、機会、脅威を特定す...
6月3日、「データマイニングに基づくパーソナライズされた情報推奨エンジン」を提供するアプリ「今日頭条...