Redisベースの分散ロックステップ-RedLock(真分布)の構築

3973 ワード

本文は簡単な本の作者から転載します:謝随安リンク:https://www.jianshu.com/p/ed53f19c3a1e
前言は、以前の「単機版redisベースの分散ロック設計実装」の文章で、2つの一般的なredis分散ロックを紹介し、実現した.しかし、この方法は、単一ノードで、ダウンタイムがない環境で問題がないことを保証するだけです.redisクラスタでは、極端な特殊なシーンに遭遇するといくつかの問題が発生します.
なぜ以前の分散ロック設計に問題があったのですか?Redisで分散ロックを実現する最も簡単な方法は、インスタンスにキー値を作成することです.作成されたキー値は一般的にタイムアウト時間があるので、各ロックは最終的に解放されます.クライアントがロックを解除したい場合は、このキー値を削除するだけです.
表面的には、この方法は役に立つようですが、実際のビジネスシーンでは、キャッシュシステムの高可用性を保証するために、redisは単一のポイントではなく、クラスタ配置であることが多いという問題があります.Redisプライマリスレーブノードのデータ同期は非同期であるため、RedisのmasterノードがSlaveノードにロックされていないときにダウンタイムしたらどうしますか?例として、
  • クライアントAは、masterノードでロックを取得する.
  • ロックがslaveに同期する前に、masterはダウンタイムし、slave
  • にロックを同期するのに間に合わなかった.
  • slaveはmasterノード
  • になる
  • クライアントBもAが持つものと同じロック
  • を得る.
    この場合、ダウンタイム中に複数のクライアントが同時にロックを持つことを許容できる場合は、このレプリケーション・ベースのスキームでは問題ありません.そうしないと、前の記事で実装した分散ロックは明らかに実行できません.このスキームでは、分散ロックのセキュリティと信頼性が保証されていないため、1番目のセキュリティ反発属性分散ロックのセキュリティと信頼性の保証には、次の3つの属性が必要です.
  • 一貫性:反発し、いつでも同じロックを持つクライアントは1つしかありません.
  • パーティションの許容性:デッドロックはなく、最終的には必ずロックされます.ロックを持っているクライアントがダウンしたり、ネットワークパーティションが発生したりしても.
  • 可用性:ほとんどのRedisノードが正常に動作している限り、クライアントはロックを取得および解放できるはずです.

  • さらに、以前の設計のもう一つの問題は、ロックを占有するスレッドの実行時間が期限切れ時間より大きい場合、別のスレッドもロックを取得し、2つのスレッドが共有リソースに同時にアクセスできるようにすることである.
    RedLockアルゴリズムでは、複製や他の暗黙的な分散協調アルゴリズムを使用しない完全に独立したN個のRedisマスターノードがあると仮定しています.従って、ロックを単一ノード環境で安全に取得および解放する方法を用いて、各単一ノードでロックを取得および解放する.
      !!!:redLock       redis  ,           ,
    RedLock         ,           ,
                       。
    

    Nを5と仮定します.この数字は比較的合理的な数値です.そのため、異なるコンピュータまたは仮想マシン上で5つのmasterノードを実行して、ほとんどの場合、同時にダウンタイムしないことを保証する必要があります.クライアントは、ロックを取得するために次の操作を行う必要があります.
  • 現在時刻(ミリ秒単位)
  • を取得
  • は、同じkeyおよびランダム値でN個のRedisに順次ロックを要求する.このステップでは、クライアントがmasterごとにロックを要求すると、ロック解放時間よりはるかに小さいタイムアウト時間があります.たとえば、ロックの自動解放時間が10秒の場合、各ノードのロック要求のタイムアウト時間は5~50ミリ秒の範囲であり、クライアントがダウンしたmasterノードで長時間ブロックされないようにします.masterノードが使用できない場合は、できるだけ早く次のmasterノードを試してください.
  • クライアントは、ロックの取得に合計どれだけの時間がかかったかを計算します.このロックは、クライアントがほとんどのmasterノードでロック(ここでは3つ)を正常に取得し、ロックの解放時間を超えない場合にのみ、取得に成功したと考えられます.
  • ロックの取得に成功した場合、ロックの有効時間は、最初のロック解除時間からロックの取得に要する時間を減算することである.
  • ロックの取得に失敗した場合、成功したロックが半分を超えない(N/2+1)ためでも、総消費時間がロックの解放時間を超えたためでも、クライアントはmasterノードごとにロックを解放します.成功していないと考えているロックであっても.

  • 失敗した再試行クライアントがロックを取得できなかった場合、このクライアントはランダムな遅延後に再試行する必要があります.ランダム遅延を採用するのは、異なるクライアントが同時に再試行して誰もロックを取得できない場合を避けるためであり、同様にクライアントが多くのRedisノードでロックを取得しようとするほど、複数のクライアントが同時にロックと再試行を競合する時間ウィンドウが小さくなる可能性が低いため、最も完璧な場合、クライアントはマルチパスでSETコマンドをすべてのRedisノードに同時に送信するべきである.ここでは、クライアントが多数のノードでロックを取得していない場合、ロックが成功したノードでロックを解除する必要があることを強調する必要があります.これにより、keyがタイムアウトしてからロックを再取得する必要はありません(ただし、ネットワークパーティションが発生し、クライアント側がRedisノードに接続できない場合、keyがタイムアウトするまで待つシステムの可用性が損なわれます).
    ロック解除ロックは、すべてのノードでロックを解除するだけで簡単です.これまでノードでロックが成功したかどうかにかかわらず、ロックを解除する必要があります.
    RedLockアルゴリズムの欠点Redlockアルゴリズムはクロック依存性が強すぎて、N個のノードのいずれかに時間ジャンプが発生すると、それによってロックセキュリティの問題を引き起こす可能性がある.信頼性の高い分散ロックの作り方を参照してください.Redlockは本当にできますか.Redis RedLockの完璧な分布式ロックですか?時間の問題でRedlockが信頼できない例を挙げた.
  • client 1はABCの3つのノードからロックを申請し、DEはネットワークの理由で
  • に到達しなかった.
  • Cノードのクロックが前に進むと、lockが
  • 期限切れになる.
  • client 2はCDEにおいてロックを獲得し、ABはネットワーク上の理由で
  • に到達しなかった.
  • クライアントt 1とクライアントt 2の両方がロック
  • を取得する.
      Redlock              ,   C     ,
    Redlock          Redlock          ,
                      ,              。
       Martin          ,                    ?
    

    同期システムモデルを仮定した上で、Redlockは正常に動作します.つまり、システムは次のプロパティを満たすことができます.
  • ネットワーク遅延境界、すなわち、パケットが
  • に到達すると仮定する.
  • プロセス停止境界、すなわちプロセス停止は、一定の最大時間内に
  • である.
  • クロックエラー境界、すなわち、悪いNTPサーバから時間
  • を取得しない.
    MartinはRedlockが本当に良い選択ではないと考えており、需要性能の分散ロックアプリケーションには重すぎてコストが高い.正確性を必要とするアプリケーションには安全ではありません.それは高危険なクロックあるいは他の上述の状況に対して信頼できない仮定を行ったため、もしあなたの応用が高性能の分布式ロックだけがどれだけ高い正確性を要求しないならば、単一ノードRedisは十分です;アプリケーションが正確性を維持したい場合は、Redlockをお勧めしません.Zookeeperなどの適切な一貫性調整システムを使用し、fencing tokenの存在を保証することをお勧めします.
    しかし、筆者は、適用シーンもそれほど絶対的ではなく、性能と正確性については、折衷案を1つだけ必要とし、高い正確性を保証しながら高い性能を保証する場合があるため、RedLockを使用するかどうかは適用シーンに適しているかどうかにかかっていると考えている.