Redis分散ロックについて


一、背景
最近Redisに関する知識を学び,Redis分散ロックの実現と応用を学んだ.この過程で,いくつかの疑問に直面し,本論文では主にこの過程で遭遇した疑問と分布ロックに関する知識点の総括を記録した.
ps.Redisが分散ロックを実現する文章,ブログ,コラムなどの参考になる資料はたくさんある.
二、分布式ロック
分散ロックといえば、次のような問題があります.
  • 1、分散ロックアプリケーションのシーンはどれらがありますか?分散ロックとは何ですか.どのような特徴がありますか.
  • 2、Redisはなぜ分散ロックに適しているのですか?
  • 3、Redisを使って分布式ロックを実現します.具体的にどのような実現方法がありますか?

  • これらの質問を持って、ネット上で多くの答えを見つけることができます.ここでは、これらの質問を簡単にまとめて記録します.
    1、分散ロックアプリケーションのシーンはどれらがありますか?分散ロックとは何ですか.どのような特徴がありますか.
    ロックの役割は、複数のプロセスまたはスレッドが同時操作で共有リソースを操作するときのリソースの正確性を保証することです.分散アプリケーションでは、1つのサービスに複数のインスタンスを配置する必要があります.分散環境での共有リソースを操作するには、分散ロックを使用して操作の正確性を保証する必要があります.
    分散ロックには、反発、再入力可能、ロックタイムアウト、高可用性などの特徴があるはずです.ここで、前述のいくつかの特徴はローカルロックの具体的な特徴と同じであり、高可用性は分散ロックに必要な重要な特徴である.
    分散ロックの適用シーンについては、最近参加したいくつかのプロジェクトを探してみましたが、実際に分散ロックに適用されているものは多くなく、在庫控除のような適用シーンが理解できます.
    2、Redisはなぜ分散ロックに適しているのか.
  • 高性能:Redis読み書き性能が高く、高い同時ロック操作シーン
  • に対応できる
  • 高信頼性:Redisは分散型システムであり、高可用性スキーム
  • を備える.
    3、Redisを使って分布式ロックを実現し、具体的にどのような実現方法がありますか?
    Redisを使用して分散ロックを実現するには、2つの条件を満たす必要があります.ロックとロック解除プロセスは原子操作でなければなりません.Redis Clusterを使用して高可用性を確保します.
    具体的なインプリメンテーションは、単一のRedisノードに基づいて実装され、複数のRedisノードに基づいて実装される高信頼性分散ロックを含む.
    三、Redisは分布式ロックを実現する
    シングルノードベースの実装
    ライン上のRedis配置は一般的にクラスタモードであり、単一ノードに基づいて実現される.すなわち、クラスタモードでは1つのmasterに対してのみロック解除操作が行われ、どのmasterであるかは、Redisのkeyで計算されたハッシュスロットに基づいて決定される必要がある(具体的にはRedis Clusterモードを知ることができる).
    ロック、ロック解除操作には複数の操作が必要であり、操作の原子性を保証する必要があり、Redisの単一コマンドとLuaスクリプトの2つの方法で原子操作を実現する.
    錠をかける
    ロックの注意事項
  • 1、ロックプロセスは原子性
  • を保証しなければならない.
  • 2、誰がロックをかけたかを保証するのは誰がロックを解除することしかできなくて、つまりRedisがロックをかけたvalueで、ロックを解除する時同じvalueに入ってこそ成功することができて、valueの唯一性を保証する
  • 3、ロックタイムアウト時間を設定し、ロック側異常がロックを解除できない場合、他のクライアントがロックを取得できないことを防止するとともに、タイムアウト時間は業務処理時間
  • より大きい.
    RedisコマンドSET lock_key unique_value NX EX secondsを使用してロックを行い、単一コマンド操作、Redisはシリアル実行コマンドであるため、ロックが成功するのは1つだけであることが保証される.
    ロック解除
    ロック解除はDELコマンドで削除され、誤ったロック解除(Aロック、Bロック)を避けるためにvalueを比較する必要があり、プロセス全体が原子性を保証するためLuaスクリプト(unlock.script)を使用する
    //      unique_value    
    if redis.call("get",KEYS[1]) == ARGV[1] then
        return redis.call("del",KEYS[1])
    else
        return 0
    end
    redis-cli  --eval  unlock.script lock_key , unique_value 

    この実装方式は,単一ノードに基づいてロック情報を保存し,高信頼性を備えていない.高い信頼性を保証するには、複数のノードに基づいて実装します.
    もう1つの欠点は、設定された期限が切れ、ビジネス処理が終了しないうちにロックを早期に解放し、他のリクエストがロックを取得し続ける可能性があることです.解決策はRedissonを用いることであり、大まかな解決原理は、ガードスレッドを開いて定期的にロックが存在するかどうかをチェックし、存在する場合keyの時間を延長し、取得しようとしたクライアントはスピンでロックを取得することである.
    https://github.com/redisson/r...
    複数のノードに基づいて実装
    RedLockアルゴリズム
    Redisの開発者Antirezが提案したRedLockアルゴリズムの基本構想は,クライアントと複数の独立したRedisインスタンスが順次ロックを要求することであり,半数以上のインスタンスとロックに成功すれば,クライアントが分散ロックを取得することに成功すると考えられる.
    実装手順は次のとおりです.
  • 1、クライアントは現在の時間
  • を取得する.
  • 2、クライアントは、N個のRedisノードのように順次ロック操作を実行する.ロック操作は単価ロックと同様に、有効期限を設定し、RedisインスタンスIDを付けるだけである.
  • 3、クライアントはすべてのRedisノードに対するロック操作を完了し、プロセス全体の合計消費時間を計算し、同時に満たす:
    * (1)               
    * (2)                
    
    この2つの条件が同時に満たされていない場合、すべてのRedisノードにロックを解除する操作を実行する.

  • RedLockアルゴリズムについては、業界の分散システム専門家Martin KleppmannAntirezと議論し、このアルゴリズムの信頼性を評価した.議論の詳細は、ロック中にクライアントがブロックされ、マシンクロックがジャンプするなど、異常な状況でRedLockが失効する可能性があるシーンについてである.(表示http://zhangtielei.com/posts/...)
    まとめ
    分散システム設計は複雑さと収益のバランスを実現し、できるだけ安全で信頼性が高く、過度な設計を避けなければならない.正確性のためであれば、業務は結果に対する要求が非常に厳しく、RedLockを使用することを提案するが、欠点は使用が重く、配置コストが高いことである.効率のために単一のRedisノードに基づく分散ロックを使用すればよい場合、このスキームの欠点は、ロックが偶発的に失効することを可能にし、単純で効率的であることである.ほとんどの場合、単一のRedisノードに基づく分散ロックを選択すればよい.
    その他
  • オンラインredisツール:https://try.redis.io/、redisコマンドの使用を熟知するために使用できます.
  • 参照:https://www.infoq.cn/article/...