著者について Leng Zhenglei は2018 年 2 月に Qunar.com DBA チームに加わりました。彼は主に、航空券業務の MySQL および Redis データベースの運用と保守管理、およびデータベース自動化運用および保守プラットフォームの一部の機能の開発を担当しています。彼はデータベース技術に強い関心を持ち、MySQL と Redis の運用・保守管理、パフォーマンス最適化において長年の経験を持っています。 1. 背景電子商取引のウェブサイトで買い物をするとき、電子商取引アプリによく見られるフラッシュセールや限定版クーポン購入、Qunar.com の列車チケット取得システムなど、同時実行性の高いシナリオに遭遇することがよくあります。これらのシナリオには、訪問者数の急増という共通の特徴があります。システム設計時に電流制限、非同期、キューイングなどによって最適化されますが、全体的な同時実行性は通常よりも数倍高くなります。同時実行の問題を回避し、在庫の過剰販売を防ぎ、ユーザーに快適なショッピング体験を提供するために、これらのシステムではロック メカニズムが使用されます。 単一プロセスの同時実行シナリオでは、同時実行の問題を回避するために、プログラミング言語と対応するクラス ライブラリ (Java の synchronized 構文や ReentrantLock クラスなど) によって提供されるロックを使用できます。 分散シナリオで異なるクライアントのスレッドによるコードとリソースへの同期アクセスを実現し、複数のスレッドで共有データを処理するセキュリティを確保するには、分散ロック テクノロジを使用する必要があります。 では、分散ロックとは何でしょうか?分散ロックは、分散システム間または異なるシステム間の共有リソースへのアクセスを制御するロック実装です。リソースが異なるシステム間または同じシステムの異なるホスト間で共有される場合、相互の干渉を防ぎ一貫性を確保するために、相互排他制御が必要になることがよくあります。 比較的安全な分散ロックには、通常、次の特性が必要です。
分散ロックを実装するには、リソースをロックするだけでなく、デッドロックやロックの失敗などの問題を回避するためにいくつかの追加機能も満たす必要があることがわかります。 2. 分散ロックの実装分散ロックを実装する方法は多数あります。最も一般的なものは次のとおりです。
Memcached の add コマンドを使用します。このコマンドはアトミック操作です。キーが存在しない場合にのみ追加が成功します。これは、スレッドがロックを取得したことを意味します。
Zookeeper の連続した一時ノードを使用して、分散ロックと待機キューを実装します。 ZooKeeper は分散アプリケーション向けに特別に設計されたフレームワークとして、一時的な znode の自動削除など、非常に優れた機能を提供します。 ZooKeeper は、分散ロックをローカル ロックのようにクライアントで使用できるようにする監視メカニズムも提供します。ロックが失敗した場合、ロックが取得されるまでブロックされます。
Google が実装した粗粒度の分散ロック サービスは、ZooKeeper と多少似ていますが、違いも多くあります。 Chubby は、シーケンサー メカニズムを通じて、要求の遅延によって発生するロック障害の問題を解決します。
単一の Redis マシンに基づいて実装された分散ロックは、やはりアトミック操作である Redis SETNX コマンドを使用する Memcached の実装に似ています。キーが存在しない場合にのみ正常に設定できます。 Redis マルチマシン実装に基づく分散ロック Redlock は、Redis 分散ロックの実装を標準化するために Redis の作者 antirez によって提案された、より安全で効果的な実装メカニズムです。 この記事では主に、Redis に基づく分散ロックのいくつかの実装方法と既存の問題について説明し、分析します。 3. Redis分散ロックRedis を分散ロックとして使用する場合、重要な目標は、プロセスが Redis 内の唯一の「トイレ」を占有することです。他のプロセスがトイレを占有しようとすると、すでに誰かがそこにしゃがんでいることがわかり、諦めるか、待ってからもう一度試す必要があります。 現在、Redis に基づく分散ロックには主に 2 つの種類があります。 1 つは単一のマシンに基づいており、もう 1 つは複数の Redis マシンに基づいています。実装方法に関係なく、分散ロックの 3 つのコア要素、つまりロック、ロック解除、ロック タイムアウトを実装する必要があります。 1. Redisスタンドアロンベースの分散ロック 1) SETNX命令を使用する ロックする最も簡単な方法は、Redis SETNX 命令を直接使用することです。この命令は、キーが存在しない場合にのみ、キーの値を value に設定します。キーがすでに存在する場合、SETNX コマンドは何もアクションを実行しません。キーはロックの一意の識別子であり、ビジネス ニーズに応じてロックされるリソースに応じて名前を付けることができます。 たとえば、特定のショッピングモールのフラッシュセールイベントで商品をロックする場合、キーを lock_resource_id に設定し、値を任意の値に設定できます。リソースが使用された後は、DEL を使用してキーを削除し、ロックを解除します。全体のプロセスは次のとおりです。 明らかに、ロックを取得するこの方法は非常に簡単ですが、前述の分散ロックの 3 つのコア要素の 1 つであるロック タイムアウトの問題という問題もあります。つまり、ビジネスロジック処理中にロックを取得するプロセスで例外が発生すると、DEL 命令が実行されず、ロックを解除できず、リソースが永久にロックされたままになる可能性があります。 そのため、SETNX を使用してロックを取得した後は、キーに有効期限を設定し、明示的に解放しなくても、一定期間後に自動的に解放されるようにして、リソースが長時間独占されるのを防ぐ必要があります。 SETNX は有効期限の設定をサポートしていないため、追加の EXPIRE 命令が必要です。全体のプロセスは次のとおりです。 このように実装された分散ロックには依然として重大な問題が残っています。 SETNX と EXPIRE の 2 つの操作は非アトミックであるため、SETNX と EXPIRE の実行の間に例外が発生すると、SETNX は正常に実行されますが、EXPIRE は実行されず、ロックが「不滅」になります。この場合、前述のロックタイムアウトの問題が発生し、他のプロセスが正常にロックを取得できなくなります。 2) SET拡張コマンドを使用する SETNX および EXPIRE 操作の非アトミック問題を解決するために、Redis SET 命令の拡張パラメータを使用して、SETNX および EXPIRE 操作をアトミックにすることができます。全体のプロセスは次のとおりです。 このSET命令では、
ただし、このアプローチでは、分散ロックのタイムアウトの問題を完全に解決することはできません。
上記の状況を回避するには、実行時間が長すぎるシナリオでは Redis 分散ロックを使用しないことをお勧めします。同時に、より安全な方法は、DEL を実行してロックを解除する前にロックを判断し、現在のロック保持者が自分自身であるかどうかを確認することです。 具体的な実装としては、ロック時に値を一意の乱数(またはスレッド ID)に設定し、ロックを解除する際には乱数が一貫しているかどうかをまず判断し、その後、ロックの有効期限が切れてサーバーによって自動的に解除されない限り、他のスレッドによって保持されているロックが誤って解除されないように解除操作を実行します。全体のプロセスは次のとおりです。 ただし、値の決定とキーの削除は 2 つの独立した操作であり、アトミックではないため、Lua スクリプトを使用して処理する必要があります。これは、Lua スクリプトを使用すると、複数の連続した命令のアトミック実行を保証できるためです。 Redis 単一ノードに基づく分散ロックは基本的に完成していますが、他のスレッドが現在のスレッド実行タイムアウトロックを事前に解放して利用してしまう問題を完全に解決していないため、完全なソリューションではなく、相対的に完成しているにすぎません。 3) Redissonの分散ロックを使用する ロックが早期に解除される問題をどのように解決できますか? ロックの再入可能機能を使用すると、ロックを取得したスレッドがタイマー付きのデーモン スレッドを開始し、expireTime/3 ごとに実行してスレッドのロックが存在するかどうかをチェックすることができます。存在する場合、ロックの有効期限は expireTime にリセットされます。つまり、デーモン スレッドは、ロックの有効期限が切れてロックが早期に解放されるのを防ぐために、ロックの「寿命を延ばす」ために使用されます。 もちろん、このデーモン プロセスのロジックをビジネスで実装するのは比較的複雑であり、未知の問題が発生する可能性があります。 現在、インターネット企業の実稼働環境で広く使用されているオープンソース フレームワークである Redisson は、この問題を非常にうまく解決します。非常にシンプルで使いやすく、Redis シングルインスタンス、Redis MS、Redis Sentinel、Redis Cluster などの複数のデプロイメント アーキテクチャをサポートしています。 興味のある方は、公式ドキュメントまたはソースコードを参照してください。 https://github.com/redisson/redisson/wiki 実装原理を図に示します (図では Redis クラスターを例にしています)。 2. Redisマルチマシン実装に基づく分散ロック、Redlock 上記の Redis スタンドアロン実装に基づく分散ロックには、実際には問題があります。つまり、ロックは 1 つの Redis ノードでのみ機能します。 Redis は Sentinel を通じて高可用性を確保していますが、Redis のレプリケーションは非同期であるため、マスターノードがロックを取得した後、データ同期が完了せずにフェイルオーバーが発生します。この時点では、他のクライアントのスレッドは引き続きロックを取得できるため、ロックのセキュリティが失われます。 全体のプロセスは次のとおりです。
このため、Redis の分散環境では、Redis の作者 antirez が分散ロックを実装するための RedLock アルゴリズムを提供しています。アルゴリズムはおおよそ次のようになります。 互いに完全に独立した N (N>=5) 個の Redis ノードがあると仮定します。マスター/スレーブ レプリケーションやその他のクラスター調整メカニズムはありません。これらの N 個のノードでロックを取得および解放するには、単一の Redis インスタンスの場合と同じ方法を使用するようにしてください。 ロックを取得するには、クライアントは次の操作を実行する必要があります。
ロックを解除するプロセスは比較的簡単です。クライアントは、ロックに失敗したノードを含むすべての Redis ノードに対してロック解除操作を開始し、ロック解除操作も実行する必要があります。 Antirez はアルゴリズムの説明でこの点を特に強調しています。何故ですか? その理由は、ノードが正常にロックされた後にクライアントに返される応答パケットが失われる可能性があるためです。この状況は非同期通信モデルで発生する可能性があります。クライアントはサーバーと正常に通信できますが、逆方向に問題が発生します。クライアントの応答タイムアウトによりロックは失敗しますが、Redis ノードに対して SET 命令が正常に実行され、ロックは成功したことを意味します。したがって、ロックを解放するときに、クライアントは、その時点でロックを取得できなかった Redis ノードに対してもリクエストを開始する必要があります。 さらに、Redis ノードがクラッシュして再起動した後にロックが失われ、ロックのセキュリティに影響が及ぶのを避けるために、antirez は遅延再起動の概念も提案しました。つまり、クラッシュ後すぐにノードを再起動せず、再起動する前に一定時間待機します。この期間は、ロックの有効期間よりも長くする必要があります。 Redlock についてさらに詳しく知りたい方は、公式ドキュメントを参照してください: https://redis.io/topics/distlock IV.結論分散システムの設計では、複雑さと利点のバランスをとることが重要です。過剰な設計を避けながら、可能な限り安全で信頼できるものにする必要があります。 Redlock は確かにより安全な分散ロックを提供できますが、それにはコストがかかり、より多くの Redis ノードが必要になります。実際のビジネスでは、単一ポイントの Redis を使用して分散ロックを実装すると、通常、ほとんどのニーズを満たすことができます。場合によっては、手動で介入してデータを入力することで、データの不整合を解決できることがあります。諺にもあるように、「テクノロジーが不十分なら、人間の介入で補うことができます!」 。 |
<<: クラウドネイティブアプリケーションを構築するために知っておくべきこと
>>: PaaS、IaaS、SaaS、Bass、Fass、サーバーレスの理解と違い
ストリーミング メディアのウェブマスターの中には、特に強力な CPU を必要とするストリーミング メ...
プロメテウスは18周年を記念して、2つのVPSモデルを特別価格で販売しています。さらに、サイト全体に...
インタレストグラフソーシャルメディアをマーケティングインタラクションに活用するには?この記事では、自...
新しいサイトの場合、最も一般的な方法は、Baidu に送信することです。ここで、Baidu に送信し...
Dell の技術を採用した VMware パブリック クラウド サービス プロバイダーである Fir...
新しいウェブサイトを最適化するのは簡単ではないと言われていますが、実際に経験してみなければ、どこに難...
北京ニュース(陳波記者)昨日、朝陽法院は第一審判決を言い渡し、北京賽金メディアテクノロジー株式会社の...
123systems からブラックフライデーセールのプロモーションメールが届きました。VPS の価格...
私は Changde Decoration Network を 2 年近く運営しています。私の考えを...
ウェブサイトの最適化を行うすべてのウェブマスターは、モール型ウェブサイトを迅速に発展させたい場合、ウ...
Fastcomet のクリスマス プロモーションが始まりました: cpanel パネルを備えたすべて...
統計がこれを証明しています。Web ページの読み込みに 4 秒以上かかると、25% のユーザーが諦め...
私は、千鹅商務網、粉魯商務網、商品安心網、麦旺網、華表市場網など、数十以上のB2Bウェブサイトを運営...
Smarthost は長い歴史を持つアメリカのホスティング会社です。1996 年に仮想ホストの運用を...
デジタル時代において、私たちの生活はさまざまなスマートデバイスやインターネット サービスにますます依...