序文 日常の開発では、フラッシュセールの注文や紅包の受け取りなどのビジネスシナリオで分散ロックが必要になります。 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 をサポートしています
複雑なマルチクラウド展開におけるデータストレージのベストプラクティスは何ですか?マルチクラウドのニー...
[[286442]] JVM には、基本型と参照型の 2 種類のデータ型が含まれています。基本的な型...
アメリカ西海岸のシアトルとサンノゼのデータセンターも、中国人が集まる人気の場所です。v.psはシアト...
10月26日、百度ウェブマスタープラットフォームとMADconが共同で主催した百度ウェブマスタープラ...
関連統計によると、中国のWitkeyユーザー数は3500万人を超えています。この巨大な基盤のおかげで...
災害復旧とは、COVID-19 によって引き起こされたビジネスの歪みを含む自然災害やサイバー攻撃の後...
2月9日午前、Meizu TechnologyとAlibaba Groupは、Alibaba Gro...
昨日(2013年2月19日)BaiduのGreen Radish Algorithmがリリースされ、...
P2Pに続いて、「クラウドファンディング」はインターネット金融業界で2番目に「急成長」している分野に...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますBaidu...
企業は俊敏性を高め、ビジネス継続性のためにクラウドとリモート監視に重点を置く必要があります。テクノロ...
[[351091]] Microsoft と Google は、ディープ ニューラル ネットワークを...
クラウド コンピューティングの発展に伴い、製造会社の日常業務にますます多くのクラウド アプリケーショ...
Zerto テクノロジー エバンジェリストの Chris Rogers が、クラウドでの災害復旧の仕...
最適化におけるテンプレートの役割: テンプレートは、Web サイトのコンテンツのレイアウトと Web...