前回の記事では、システムパフォーマンスを向上させるためのキャッシュを行うローカルメモリの使い方「キャッシュ実践編(その1)」について説明しました。また、キャッシュの故障の問題を解決するためにロックを使用する方法についても説明しました。ただし、ローカル ロック方式は分散シナリオには適用できないため、この記事では、ローカル ロックの問題を解決するために分散ロックを導入する方法について説明します。この記事のすべてのコードとビジネスは、私のオープンソース プロジェクト PassJava に基づいています。 この記事の主な内容は次のとおりです。 1. ローカルロックの問題まず、ローカル ロックの問題を確認しましょう。 現在、トピックのマイクロサービスは 4 つのマイクロサービスに分割されています。フロントエンドのリクエストが届くと、さまざまなマイクロサービスに転送されます。フロントエンドが 100,000 件のリクエストを受信し、各マイクロサービスが 25,000 件のリクエストを受信した場合、キャッシュに障害が発生すると、各マイクロサービスはデータベースにアクセスするときにロックし、キャッシュの破損を防ぐためにロック (同期またはロック) を通じて独自のスレッド リソースをロックします。 これはローカル ロック方式であり、分散環境ではデータの不整合が発生する可能性があります。たとえば、サービス A がデータを取得した後、キャッシュ キー = 100 を更新します。サービス B はサービス A のロックによって制限されず、キャッシュ キー = 99 に更新を送信します。最終結果は 99 または 100 になる可能性がありますが、これは不明な状態であり、予想される結果と一致しません。フローチャートは次のとおりです。 2. 分散ロックとは何か上記のローカル ロックの問題に基づいて、分散クラスター環境をサポートするロックが必要です。DB をクエリする場合、1 つのスレッドだけがアクセスでき、他のスレッドは最初のスレッドがロック リソースを解放するまで待機してから実行を続行する必要があります。 人生における例: ロックをドアの外にある鍵と考え、すべての同時スレッドを人として考えることができます。全員が部屋に入りたいのですが、部屋に入ることができるのは 1 人だけです。誰かが入ってくるとドアは施錠され、その人が出てくるまで他の人は待たなければなりません。 次の図に示すように、分散ロックの基本原理を見てみましょう。 上の図の分散ロックを分析してみましょう。
簡単な説明: すべてのリクエスト スレッドは、「スロットを占有」するために同じ場所に移動します。スロットがある場合は、ビジネス ロジックが実行されます。スロットがない場合、他のスレッドが「スロット」を解放する必要があります。このピットはすべてのスレッドに表示されます。このピットを Redis キャッシュまたはデータベースに配置できます。この記事では、Redis を「分散ピット」として使用する方法について説明します。 3. Redis SETNXRedis は、誰でもアクセス可能な場所であるため、「ピットを占領する」場所として使用できます。 Redis を使用して分散ロックを実装するためのソリューションはいくつかあります。私たちは皆、SETNX コマンド (キーを特定の値に設定する) を使用します。ただ、高レベルソリューションによって渡されるパラメータの数が異なり、異常な状況が考慮されるだけです。 このコマンドを見てみましょう。 SETNX は、存在しない場合に set する略語です。つまり、キーが存在しない場合にはキーの値を設定し、存在する場合には何もしません。 Redis コマンドラインでの実行方法は次のとおりです。
redis コンテナに入り、SETNX コマンドを試すことができます。 まずコンテナを入力します:
次に、SETNX コマンドを実行します。キー wukong に対応する値を 1111 に設定します。
設定が成功したことを示す OK を返します。コマンドを繰り返します。 nil が返された場合は設定が失敗したことを意味します。 4. ブロンズプランまず、Redis の SETNX コマンドを使用して、最も単純な分散ロックを実装します。 3.1 ブロンズ原則 フローチャートを見てみましょう:
コード例は以下のとおりです。 Java の setnx コマンドに対応するコードは setIfAbsent です。 setIfAbsent メソッドの最初のパラメーターはキーを表し、2 番目のパラメーターは値を表します。
ちょっとした質問ですが、なぜしばらく眠る必要があるのでしょうか? プログラムに再帰呼び出しが含まれているため、スタック スペース オーバーフローが発生する可能性があります。 3.2 ブロンズソリューションの欠点 青銅は最も基本的なものであり、間違いなく多くの問題をもたらすため、青銅と呼ばれています。 ある家族のシナリオを想像してみてください。夜、小空がドアの鍵を開けて一人で部屋に入り、電気をつけたら、突然電気が消えてしまいます。小空はドアを開けて外に出たいのですが、ドアの鍵が見つかりません。そうすると、シャオミンは入れなくなり、外にいる人も入れなくなります。 技術的な観点から見ると、setnx はロックを正常に取得しますが、ビジネス コードで例外が発生したり、サーバーがクラッシュしたりして、ロックを削除するロジックが実行されず、デッドロックが発生します。 では、このリスクを回避するにはどうすればよいでしょうか? ロックの自動有効期限を設定します。一定時間が経過すると、ロックは自動的に削除され、他のスレッドがロックを取得できるようになります。 4. シルバープラン4.1 実生活からの例 上記のブロンズ ソリューションにはデッドロックの問題があるため、上記のリスク回避ソリューションを使用して設計します。これがシルバー ソリューションです。 現実生活から別の例を見てみましょう。Xiaokong はドアのロックを解除した後、スマートロックに砂時計のカウントダウンを設定しました。砂時計が終わると、ドアのロックが自動的に開きました。突然部屋の電気が消えても、一定時間後に自動的に鍵が開き、他の人が入室できるようになります。 4.2 技術概略図 ブロンズ ソリューションとの違いは、ロックが正常に占有された後に、ロックの有効期限が設定される点です。これら 2 つのステップは段階的に実行されます。次の図に示すように: 4.3 サンプルコード Redisキーを消去するためのコードは次のとおりです。
完全なコードは次のとおりです。
4.4 シルバーソリューションの欠点 Silver ソリューションは、スレッド例外またはサーバー クラッシュによりロックが解放されないという問題を解決しているように見えますが、まだ他の問題が残っています。 ロックの占有と有効期限の設定は 2 つのステップで実行されるため、この 2 つのステップの間に例外が発生すると、ロックの有効期限は正常に設定されません。 したがって、ブロンズ ソリューションと同じ問題、つまりロックの有効期限が切れないという問題があります。 5. 黄金の計画5.1 アトミック命令 上記のシルバー ソリューションでは、ロックの占有とロックの有効期限の設定が 2 つのステップで実行されます。この時点で、トランザクションのアトミック性について考えることができます。 原子性: 複数のコマンドが正常に実行されるか、まったく実行されないかのいずれかになります。 ロックの占有 + ロックの有効期限の設定という 2 つのステップを 1 つのステップで実行します。 Redis はまさにこの操作をサポートしています:
次のコマンドでキーの変更を確認できます。
以下は、キーを設定し、有効期限を設定する方法を示しています。注意: コマンドを実行する前にキーを削除する必要があります。クライアントまたはコマンドを通じて削除できます。
実行結果は下の図のようになります。ttl コマンドを実行するたびに、wukong の有効期限が短くなるのがわかります。最終的には-2(期限切れ)になります。 5.2 技術概略図 ゴールドプランとシルバープランの違い: ロックを取得する際に、ロックの有効期限も設定する必要があります。これは、正常に実行されるか、実行されないかのいずれかになるアトミック操作です。次の図に示すように: 5.3 サンプルコード ロック値を 123 に設定し、有効期限を 10 秒に設定します。 10 秒経過してもロックがまだ存在する場合、ロックは解除されます。
5.4 黄金の解決策の欠点 現実の例を取り上げ、黄金の計画の欠陥を見てみましょう。 5.4.1 ユーザーAがロックを奪取する
5.4.2 ユーザーBがロックを奪取する
5.4.3 ユーザーCがロックを奪取する
上記のケースから、ユーザー A がタスクを処理するのに必要な時間がロックが自動的にクリア (ロック解除) される時間よりも長いため、ロックが自動的にロック解除された後に他のユーザーがロックを奪取したことがわかります。ユーザー A がタスクを完了すると、他のユーザーが押収したロックを積極的に解除します。 なぜここで他人の鍵が開けられるのでしょうか?ロック番号はすべて「123」と呼ばれ、ユーザーAだけがロック番号を認識します。 「123」という番号の鍵を見つけると、彼はそれを開けます。その結果、ユーザー B のロックが解除されます。この時点で、ユーザーBはタスクを完了していないので、当然怒っています。 6. プラチナプラン6.1 実生活からの例 上記の黄金比の解決策の欠点も簡単に解決できます。ロックごとに異なる番号を設定するだけです。 下の図に示すように、B が押収したロックは青色で、A が押収した緑色のロックとは異なります。このため、A では開けられません。 理解しやすいように動的な図を作成しました: アニメーションデモ 静止画はより高解像度なので、ぜひご覧ください: 6.2 技術概略図 ゴールドプランとの違い:
6.3 コード例
6.4 プラチナソリューションの欠点 上記の解決策は完璧に思えますが、まだ問題が残っています。ステップ 4 と 5 はアトミックではありません。
では、このリスクを回避するにはどうすればよいでしょうか?ダイヤモンドソリューションの登場です。 7. ダイヤモンドプラン上記のスレッド A のロック照会および削除のロジックはアトミックではないため、ロック照会および削除はアトミック命令として操作できます。 7.1 技術概略図 下の図のように、赤丸で囲った部分がダイヤモンド解の差分です。アトミック操作を実現するには、スクリプトを使用して削除を実行します。 7.2 コード例 スクリプトを使用して削除するにはどうすればいいですか? まず、この Redis 固有のスクリプトを見てみましょう。
このスクリプトは、プラチナ プランのキーの取得および削除の方法と非常によく似ています。まず、KEYS[1]の値を取得し、KEYS[1]の値がARGV[1]の値と等しいかどうかを判断します。等しい場合はKEYS[1]を削除します。 では、このスクリプトを Java プロジェクトでどのように実行するのでしょうか? 2 つのステップがあります。まずスクリプトを定義します。次に、redisTemplate.execute メソッドを使用してスクリプトを実行します。
上記のコードでは、KEYS[1]は「lock」に対応し、ARGV[1]は「uuid」に対応しています。つまり、lockの値がuuidと等しい場合、lockは削除されます。 この Redis スクリプトは、Redis に組み込まれた Lua 環境によって実行されるため、Lua スクリプトとも呼ばれます。 ダイヤモンドソリューションは完璧ですか?もっと良い解決策はあるでしょうか? 次の記事では、分散ロックのもう 1 つの優れたソリューションである Redisson を紹介します。 8. 結論この記事では、分散ロックの問題をローカル ロックの問題を通じて拡張します。次に、5 つの分散ロック ソリューションが紹介され、最も単純なものから最も複雑なものまで、さまざまなソリューションの改善点が説明されました。 上記のソリューションの継続的な進化により、システム内のどこに異常な状況が存在する可能性があるか、また、それをより適切に処理する方法がわかります。 同様に、この進化する考え方は他のテクノロジーにも適用できます。 以下に、上記 5 つのソリューションの欠点と改善点をまとめます。 ブロンズプラン:
シルバープラン:
ゴールドソリューション:
プラチナプラン:
ダイヤモンドプラン:
王様の計画、また次回の記事でお会いしましょう〜 上記のコードはすべて、PassJava オープン ソース プロジェクトに基づいています。バックエンド、フロントエンド、ミニプログラムは同じリポジトリにアップロードされ、GitHub または Code Cloud からアクセスできます。住所は以下の通りです。 Github: https://github.com/Jackson0714/PassJava-Platform コードクラウド: https://gitee.com/jayh2018/PassJava-Platform サポートチュートリアル: www.passjava.cn 参考文献: http://redis.cn/commands/set.html https://www.bilibili.com/video/BV1np4y1C7Yf この記事はWeChatの公開アカウント「Wukong Chats about Architecture」から転載したものです。下のQRコードからフォローできます。この記事を転載する場合はWukong Chat Architecture公式アカウントまでご連絡ください。 |
>>: Kafka 2.8.0 がリリースされ、正式に ZooKeeper から分離しました。
インターネットは、人々が愛を見つけるための重要な場所になりつつある中国国際放送、北京、2月11日のニ...
過去2年間で、人工知能(AI)は研究・概念レベルから応用レベルへと徐々に移行し、ますます多くの企業が...
[[428766]]最近、私はほとんどの余暇時間を、シンプルな RPC フレームワーク (初心者でも...
政策の成果と市場の需要に後押しされ、我が国のクラウド コンピューティング市場の規模は拡大を続け、産業...
ブログは、ウェブログ、ブログ、またはブログとも呼ばれ、個人によって管理され、新しい記事が随時公開され...
7月5日夜、イタリアの遠隔操作ソフトメーカー「ハッキングチーム」の内部情報が流出した。その衝撃はスノ...
ちょうど今、Tencent Cloud のオープンソース プロジェクト Crane (クラウド リソ...
始めたばかりの頃は、オンラインでさまざまな記事やチュートリアルを読み、さまざまな分野を探索し、絶えず...
シンガポールのクラウドサーバー raksmart は、米国のクラウドサーバー、香港のクラウドサーバー...
2020年、世界はユニークな形で新たな章を開きました。新型コロナウィルスの流行の影響により、全世界が...
9月29日午後、大手3社は本日同時に通知を出し、携帯電話パッケージの月間通信量を未確定にするサービス...
「アリペイのコンプライアンス部門は最近、すべてのP2P資金フロー協力にいくつかの調整を加えることを決...
host1plus.com 仮想ホストのサーバーは 1000M ポートを使用します。cPanel ま...
このタイトルを見ると、誰かが以前に理由をまとめたことに誰もが間違いなく気づいたでしょうが、Xiao ...
調査会社ガートナーは、企業が生成するデータのうち、従来の集中型データセンターやクラウド プラットフォ...