序文 日常の開発では、フラッシュセールの注文や紅包の受け取りなどのビジネスシナリオで分散ロックが必要になります。 Redis は分散ロックとして使用するのに非常に適しています。この記事では、Redis 分散ロックの正しい使用方法について 7 つのソリューションに分けて説明します。何か間違っている点がありましたら、ご指摘ください。一緒に学び、成長していきましょう。 公式アカウント:「カタツムリを拾う少年」
分散ロックとは何ですか? 分散ロックは、実際には、分散システム内のさまざまなプロセスが共有リソースにアクセスできるように制御するロックの実装です。重要なリソースが異なるシステム間または同じシステムの異なるホスト間で共有される場合、相互の干渉を防ぎ一貫性を確保するために、相互排他制御が必要になることがよくあります。 まず、信頼性の高い分散ロックに必要な機能について見てみましょう。
Redis 分散ロックソリューション 1: SETNX + EXPIRE Redis 分散ロックに関して言えば、多くの人はすぐに setnx+ expire コマンドを思い浮かべるでしょう。つまり、まず setnx を使用してロックを取得します。ロックが取得された場合は、expire を使用してロックの有効期限を設定し、ロックの解除を忘れないようにします。 SETNX は SET IF NOT EXISTS の略です。毎日のコマンドの形式は SETNX キー値です。キーが存在しない場合は、SETNX は正常に 1 を返します。キーが既に存在する場合は、0 を返します。 電子商取引ウェブサイト上の製品がフラッシュセールを行っていると仮定します。キーは key_resource_id に設定でき、値は任意の値に設定できます。疑似コードは次のとおりです。
ただし、このソリューションでは、setnx コマンドと expire コマンドが分離されており、アトミック操作ではありません。 setnx を実行してロックを実行した後、有効期限を設定するために expire を実行しようとしたときにプロセスがクラッシュしたり、メンテナンスのために再起動する必要が生じたりした場合、ロックは「不滅」となり、「他のスレッドはロックを取得できなくなります」。 Redis 分散ロック ソリューション 2: SETNX + 値は (システム時間 + 有効期限) 最初の解決策「異常なロックを解除できないシナリオ」を解決するために、一部の友人は、有効期限を setnx の値に入れることができると考えています。ロックに失敗した場合は、値を取り出して再度確認してください。ロックコードは次のとおりです。
このソリューションの利点は、expire で有効期限を個別に設定する操作を巧みに削除し、「有効期限」を setnx の値に入れることです。ソリューション 1 で例外が発生したときにロックを解除できないという問題を解決しました。ただし、このソリューションには他にも欠点があります。
Redis 分散ロック ソリューション 3: Lua スクリプトの使用 (SETNX + EXPIRE 命令を含む) 実際、Lua スクリプトを使用してアトミック性を確保することもできます (setnx および expire 命令を含む)。 Lua スクリプトは次のとおりです。
ロックコードは次のとおりです。
この計画と計画 2 を比較すると、どちらが良いと思いますか? Redis 分散ロック ソリューション 4: SET 拡張コマンド (SET EX PX NX) Lua スクリプトを使用して 2 つの命令 SETNX + EXPIRE のアトミック性を保証することに加えて、Redis の SET 命令を巧みに使用してパラメータを拡張することもできます。 (SET キー値 [EX 秒] [PX ミリ秒] [NX|XX]) これもアトミックです。 キー値の設定[EX 秒][PX ミリ秒][NX|XX]
疑似コードデモは次のとおりです。
ただし、この解決策にはまだ問題がある可能性があります。
解決策5: SET EX PX NX + 一意のランダム値を確認してから削除する ロックは他のスレッドによって誤って削除される可能性があるため、値に現在のスレッドに固有の乱数を設定し、削除時にそれをチェックします。疑似コードは次のとおりです。
ここで、「現在のスレッドによってロックが追加されたかどうかを判断する」ことと「ロックを解放する」ことはアトミック操作ではありません。ロックを解除するために jedis.del() が呼び出されると、ロックは現在のクライアントに属しなくなり、他のクライアントによって追加されたロックが解除されます。 より厳密にするために、代わりに Lua スクリプトが一般的に使用されます。 lua スクリプトは次のとおりです。
Redis 分散ロック ソリューション 6: Redisson フレームワーク ソリューション 5 では、「ロックの有効期限が切れて解除され、業務が完了しない」という問題が依然として残る可能性があります。ロックの有効期限をもう少し長く設定すれば十分だと考える友人もいます。実際に、ロックを取得したスレッドに対して時間指定のデーモン スレッドを起動し、一定の間隔でロックがまだ存在するかどうかを確認できるかどうかを想像してみましょう。そうなる場合、ロックの有効期限が延長され、期限切れによりロックが早期に解除されるのを防ぎます。 現在のオープンソースフレームワークRedissonはこの問題を解決します。 Redisson の基本的な概略を見てみましょう。 スレッドが正常にロックされるとすぐに、ウォッチドッグが開始されます。 10 秒ごとにチェックするバックグラウンド スレッドです。スレッド 1 がまだロックを保持している場合、ロック キーの有効期間は継続的に延長されます。そのため、Redisson は Redisson を使用して、「ロックの有効期限が切れて解除されても業務が完了しない」という問題を解決します。 Redis 分散ロックソリューション 7: 複数のマシンで実装された分散ロック Redlock+Redisson 前の 6 つのソリューションは、スタンドアロン バージョンに関する議論のみに基づいており、まだ完璧ではありません。実際、Redis は一般的にクラスターでデプロイされます。 スレッド 1 が Redis マスター ノードのロックを取得したが、ロックされたキーがスレーブ ノードに同期されていない場合。ちょうどこのとき、マスターノードに障害が発生し、スレーブノードがマスターノードにアップグレードされます。スレッド 2 は同じキーでロックを取得できますが、スレッド 1 がすでにロックを取得しているため、ロックのセキュリティは失われます。 この問題を解決するために、Redis の作者 antirez は、高度な分散ロック アルゴリズムである Redlock を提案しました。 Redlock の中心的なアイデアは次のとおりです。 複数の Redis マスターをデプロイして、同時に障害が発生しないようにします。これらのマスターノードは互いに完全に独立しており、マスターノード間でデータの同期は行われません。同時に、これらの複数のマスター インスタンスでロックを取得および解放するには、単一の Redis インスタンスの場合と同じ方法が使用されるようにする必要があります。 現在 5 つの Redis マスター ノードがあり、これらの Redis インスタンスが 5 台のサーバー上で実行されていると想定します。 RedLock の実装手順は次のとおりです。 1. 現在の時刻をミリ秒単位で取得します。 2. 5 つのマスターノードに順番にロックを要求します。クライアントはネットワーク接続と応答のタイムアウトを設定します。タイムアウトはロックの有効期限よりも短くする必要があります。 (ロックが 10 秒後に自動的に期限切れになると仮定すると、タイムアウトは通常 5 ~ 50 ミリ秒の間になります。タイムアウトが 50 ミリ秒であると仮定します)。タイムアウトが発生した場合は、マスターノードをスキップし、できるだけ早く次のマスターノードを試してください。 3. クライアントは、現在の時刻からロックの取得が開始された時刻 (つまり、手順 1 で記録された時刻) を引いて、ロックの取得に使用された時刻を取得します。ロックが正常に取得されるのは、Redis マスター ノードの半分以上 (N/2+1、ここでは 5/2+1=3 ノード) がロックを取得し、使用された時間がロックの有効期限よりも短い場合のみです。 (上図のように、10秒>30ms+40ms+50ms+4m0s+50ms) ロックが取得されると、キーの実際の有効期間が変わるため、ロックの取得に使用された時間を減算する必要があります。 ロックの取得に失敗した場合 (少なくとも N/2+1 個のマスター インスタンスでロックが取得されていないか、ロックの取得時間が有効時間を超えている場合)、クライアントはすべてのマスター ノードでロックを解除する必要があります (一部のマスター ノードが正常にロックされていない場合でも、ロックが網をすり抜けるのを防ぐためにロックを解除する必要があります)。 簡略化された手順は次のとおりです。
Redisson はロックの redLock バージョンを実装します。興味があればぜひ行って学んでみてくださいね〜 参考文献と謝辞 Redisシリーズ: 分散ロック[1] Redis分散ロックソリューションの簡単な分析[2] Redis分散ロックの詳細な説明[3] Redlock: Redis分散ロックの最も強力な実装 この記事はWeChatの公開アカウント「カタツムリを拾う少年」から転載したもので、著者はカタツムリを拾う少年です。この記事を転載する場合は、カタツムリを採る少年の公式アカウントまでご連絡ください。 |
<<: 分散トランザクション2PCおよび3PCモデルを徹底的に習得する
>>: VMware は仮想化を加速するために SmartNIC をサポートしています
メガレイヤーはどうですか?メガレイヤーUSAはどうですか?米国サンノゼの標準ネットワーク回線を備えた...
ここでは、それほど深い意味はないが、いくつかの小さな方法をまとめます。これが皆さんのお役に立てば幸い...
クラウド ネイティブは、企業がビジネスを展開する際の主な選択肢の 1 つになっています。利点は、アプ...
ミニプログラムの台頭に直面して、教育業界はどのようにその波に乗るべきでしょうか?この記事では、教育業...
uuuvps (Sanyou Cloud) は、今年の Double Eleven に、香港 CN2...
毎日ウェブサイトに数記事を更新することは、ウェブマスターがしなければならないことですが、更新した記事...
多くの人がウェブサイトを最適化する際、コンテンツと外部リンクに重点を置いており、基本的にこの2つの側...
マーケティング業界の伝説的人物である石玉竹は、「巨人」、「美百品」、「黄金パートナー」などを通じて、...
批判しているのではなく、自分の意見を述べているだけです数日前、私は Shi Xiaorui 氏が書い...
中国IDCレビューネットワークは1月10日に次のように報じた。「WebHosting.infoが発表...
1. バージョン管理を理解するバージョン管理とは何ですか?本当に必要ですか?バージョン管理は、特定の...
業界関係者は、今回の是正措置はWeChatのユーザー活動などの指標に影響を及ぼすとみているが、WeC...
WeChatパブリックアカウントを0から1、そしてNにまで成長させた運営者として、 WeChatパブ...
私自身の業務経験や情報をもとにまとめたブランドマーケティング運用マニュアルです。ブランド マーケティ...
Myrsk のアトランタ データ センターでは、驚きの価格で KVM プロモーションを実施しています...