Redis に基づく分散ロックと Redlock アルゴリズム

Redis に基づく分散ロックと Redlock アルゴリズム

[[414221]]

この記事はWeChatの公開アカウント「UP Technology Control」から転載したもので、著者はconan5566です。この記事を転載する場合は、UP Technology Controlの公式アカウントまでご連絡ください。

シングルプロセスシステムでは、複数のスレッドが同時に変数(可変共有変数)を変更できる場合、変数の同時変更を排除するために、変数またはコードブロックを同期して、変数を変更するときに線形に実行できるようにする必要があります。

同期の本質はロックを通じて実現されます。一度に 1 つのスレッドだけが同じコード ブロックを実行できるようにするには、どこかにマークを付ける必要があります。このマークはすべてのスレッドに表示される必要があります。マークが存在しない場合は設定可能です。後続の他のスレッドは、マークがすでに存在していることを検出すると、マークを持つスレッドが同期コード ブロックを終了し、マークをキャンセルするまで待機してから、マークの設定を試行します。このマークはロックとして理解できます。

すべてのスレッドがマークを見ることができる限り、異なる場所でロックを実装する方法も異なります。たとえば、Java では、同期によってオブジェクト ヘッダーにマークが設定されます。 Lock インターフェースの実装クラスは、基本的に volitile によって変更される int 変数にすぎず、これにより各スレッドが int の可視性とアトミックな変更を持つことが保証されます。 Linux カーネルは、マーキングにミューテックスやセマフォなどのメモリ データも使用します。

実際には、メモリ データをロックに使用することに加えて、相互に排他的なロックも使用できます (相互に排他的なケースのみを考慮します)。例えば、フローテーブル内のシリアル番号と冪等性チェックの時間を組み合わせて、解除されないロックとみなしたり、特定のファイルの存在をロックとして利用したりすることができます。マークを変更するときにのみ、アトミック性とメモリの可視性を確保する必要があります。

1 配布とは何ですか?

分散CAP理論は次のように語っています。

一貫性、可用性、およびパーティション耐性を同時に満たす分散システムはありません。最大で 2 つしか満たすことができません。

現在、多くの大規模な Web サイトやアプリケーションが分散形式で展開されています。分散シナリオにおけるデータの一貫性の問題は常に重要なトピックです。 CAP 理論に基づくと、多くのシステムは設計の初期段階でこれら 3 つの間でトレードオフを行う必要があります。インターネット分野のほとんどのシナリオでは、システムの高可用性と引き換えに強力な一貫性を犠牲にする必要があり、システムでは結果的一貫性のみを確保する必要があることがよくあります。

分散シナリオ

これは主に、複数の同一サービスが同時に開始されるクラスター モードを指します。

多くのシナリオでは、データの最終的な一貫性を保証するために、分散トランザクションや分散ロックなど、それをサポートする多くの技術的ソリューションが必要です。多くの場合、メソッドは同じスレッドによってのみ同時に実行できるようにする必要があります。スタンドアロン環境では、Java が提供する並行性 API を通じてこの問題を解決できますが、分散環境ではそれほど簡単ではありません。

  • 分散シナリオとスタンドアロン シナリオの最大の違いは、マルチスレッドではなくマルチプロセスであることです。
  • 複数のスレッドがヒープ メモリを共有できるため、メモリをタグの保存場所として簡単に使用できます。プロセスは同じ物理マシン上に存在しない可能性もあるため、マークはすべてのプロセスが参照できる場所に保存する必要があります。

分散ロックとは何ですか?

  • 分散モデルでデータのコピーが 1 つしかない場合 (または制限されている場合)、特定の時点でデータを変更するプロセスの数を制御するためにロック テクノロジが必要です。
  • スタンドアロン モードのロックと比較すると、プロセスの可視性を確保するだけでなく、プロセスとロック間のネットワークの問題も考慮する必要があります。 (分散環境では問題が複雑になる主な理由は、ネットワークの遅延と信頼性の低さを考慮する必要があるためだと思います...大きな落とし穴です)
  • 分散ロックではタグをメモリに保存できますが、メモリは特定のプロセスによって割り当てられるのではなく、Redis や Memcache などのパブリック メモリによって割り当てられます。データベースやファイルなどを使用してロックを作成する場合、タグが相互に排他的である限り、実装は単一のマシンの場合と同じです。

2 どのような分散ロックが必要ですか?

分散アプリケーション クラスターでは、同じメソッドは 1 台のマシン上の 1 つのスレッドによってのみ同時に実行されることが保証されます。

このロックは再入可能ロックである必要があります(デッドロックを回避するため)

このロックはブロッキング ロックとして最適です (ビジネス ニーズに基づいてこのロックを使用するかどうかを検討してください)

このロックは公平なロックとして最適です (ビジネス ニーズに基づいてこのロックを使用するかどうかを検討してください)

可用性の高いロック取得およびロック解放機能

ロックの取得と解放のパフォーマンスが向上しました

コードの実装

  1. パブリックインターフェイス IDistributedLock
  2. {
  3. ILockResult ロック(文字列リソースキー);
  4. ILockResult ロック(文字列リソースキー、TimeSpan 有効期限);
  5. ILockResult ロック(文字列リソースキー、有効期限の TimeSpan、待機時間の TimeSpan、再試行時間の TimeSpan);
  6. ILockResult Lock(文字列 resourceKey、TimeSpan expiryTime、TimeSpan waitTime、TimeSpan retryTime、CancellationToken cancellationToken);
  7. タスク<ILockResult> LockAsync(文字列リソースキー);
  8. Task<ILockResult> LockAsync(文字列リソースキー、TimeSpan 有効期限);
  9. Task<ILockResult> LockAsync(文字列リソースキー、有効期限の時間範囲、待機時間の時間範囲、再試行時間の時間範囲);
  10. Task<ILockResult> LockAsync(文字列 resourceKey、TimeSpan expiryTime、TimeSpan waitTime、TimeSpan retryTime、CancellationToken cancellationToken);
  11. }
  12.  
  13. パブリックインターフェイス ILockResult: IDisposable
  14. {
  15. 文字列 LockId { 取得; }
  16. bool IsAcquired { 取得; }
  17. int ExtendCount { 取得; }
  18. }
  1. クラス EndPoint:RedLock.RedisLockEndPoint
  2. {
  3. プライベート読み取り専用文字列 _connectionString;
  4. パブリックエンドポイント(文字列接続文字列)
  5. {
  6. _connectionString = 接続文字列;
  7. //139.196.40.252、パスワード=xstudio、デフォルトデータベース = 9
  8. var接続= connectionString.Split( ',' );
  9. var dict = 新しい辞書<文字列, 文字列>();
  10. foreach (var 項目in  繋がり
  11. {
  12. var keypar = item.Split( '=' );
  13. (keypar.長さ>1)の場合
  14. {
  15. dict[キーパー[0]] = キーパー[1];
  16. }
  17. }
  18. this.EndPoint = 新しい System.Net.DnsEndPoint(接続[0], 6379);
  19. if (dict.TryGetValue( "password" , out string password ))
  20. {
  21. this.Password =パスワード;
  22. }
  23. if (dict.TryGetValue( "defaultDatabase" , out string defaultDatabase) && int .TryParse(defaultDatabase, out  整数 データベース))
  24. {
  25. RedisDatabase =データベース;
  26. }
  27. }
  28. }
  1. [エクスポート(typeof(IDistributedLock))]
  2. クラス InnerLock: IDistributedLock
  3. {
  4. プライベート静的Lazy<RedLock.RedisLockFactory> _factory;
  5.  
  6. 静的InnerLock()
  7. {
  8. _factory = new Lazy<RedisLockFactory>(() => new RedisLockFactory(新しい EndPoint(ConfigurationManager.AppSettings[ "Redis" ])), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
  9. }
  10. パブリックILockResult Lock(文字列リソースキー)
  11. {
  12. 新しい LockResult(_factory.Value.Create (resourceKey, TimeSpan.FromDays (1)))を返します
  13. }
  14.  
  15. パブリックILockResult ロック(文字列リソースキー、TimeSpan 有効期限)
  16. {
  17. 新しい LockResult(_factory.Value.Create ( resourceKey , expiryTime))を返します
  18. }
  19.  
  20. パブリックILockResult ロック (文字列リソース キー、有効期限の時間、待機時間の時間、再試行時間の時間)
  21. {
  22. 新しい LockResult(_factory.Value.Create (resourceKey, expiryTime, waitTime, retryTime))返します
  23. }
  24.  
  25. パブリックILockResult Lock(文字列 resourceKey、TimeSpan expiryTime、TimeSpan waitTime、TimeSpan retryTime、CancellationToken cancellationToken)
  26. {
  27. 新しい LockResult(_factory.Value.Create (resourceKey、expiryTime、waitTime、retryTime、cancelationToken))返します
  28. }
  29.  
  30. パブリック非同期タスク<ILockResult> LockAsync(文字列リソースキー)
  31. {
  32. var result = _factory.Value.CreateAsync(resourceKey, TimeSpan.FromDays(1)) を待機します。
  33. 新しいLockResult(result)を返します
  34. }
  35.  
  36. パブリック非同期タスク<ILockResult> LockAsync(文字列リソースキー、タイムスパン有効期限)
  37. {
  38. var result = _factory.Value.CreateAsync(resourceKey, expiryTime) を待機します。
  39. 新しいLockResult(result)を返します
  40. }
  41.  
  42. パブリック非同期 Task<ILockResult> LockAsync(文字列リソースキー、有効期限の時間範囲、待機時間の時間範囲、再試行時間の時間範囲)
  43. {
  44. var result = await _factory.Value.CreateAsync(resourceKey、expiryTime、waitTime、retryTime);
  45. 新しいLockResult(result)を返します
  46. }
  47.  
  48. パブリック非同期 Task<ILockResult> LockAsync(文字列リソースキー、有効期限時間、待機時間時間、再試行時間時間、キャンセルトークンキャンセルトークン)
  49. {
  50. var result = await _factory.Value.CreateAsync(resourceKey、expiryTime、waitTime、retryTime、cancelationToken);
  51. 新しいLockResult(result)を返します
  52. }
  53. }
  54.  
  55. クラス LockResult: ILockResult
  56. {
  57. プライベート IRedisLock _lock;
  58. パブリックLockResult(IRedisLock redisLock)
  59. {
  60. _lock = redisLock;
  61. }
  62.  
  63. パブリック文字列 LockId => _lock.LockId;
  64.  
  65. パブリックブール IsAcquired => _lock.IsAcquired;
  66.  
  67. 公共  int ExtendCount => _lock.ExtendCount;
  68.  
  69. パブリックvoid Dispose()
  70. {
  71. _lock.Dispose();
  72. }
  73. }

https://github.com/samcook/RedLock.net

https://github.com/StackExchange/StackExchange.Redis/

<<:  テンセント(ホストセキュリティ)がガートナーの「クラウドワークロード保護プラットフォーム市場ガイド」レポートに掲載されました

>>:  3分レビュー! 2021年7月のクラウドコンピューティング分野の重要な動向を簡単に紹介します

推薦する

検索エンジンマーケティングにおける SEO と SEM の違い

まず、定義上、SEM は検索エンジン マーケティングであり、SEO は検索エンジン最適化です。 SE...

効果的なマルチクラウドコスト管理のための 8 つのステップ

企業がマルチクラウドを導入することでコストを節約し、生産性を向上できることはよく知られています。しか...

ページコードの最適化について議論する際に無視できないいくつかの小さな詳細

2012 年の初めに、Baidu はアルゴリズムに一定の調整を加え始め、サイトの内部要因、特に以前は...

IDC AIクラウドサービスレポート:アリババの音声AIと会話型AIの市場シェアが再び1位に

12月23日、国際的に権威のある調査機関IDCは「中国AIクラウドサービス市場半期調査レポート202...

テンセントマーケティングケーススタディ: モバイル QQ vs. WeChat

5月28日、メディアはテンセントのユーザーに対して大きなジョークを飛ばした。このジョークの背後にある...

天津がインターネット企業の新たな拠点に:免税、家賃補助

天津経済技術開発区とその周辺地域、漢沽区、塘沽区、大港区などの沿海地域は、投資を誘致する沿海新興地域...

UCloudは上海脳知能プロジェクトを全面的にサポートし、「上海脳」を共同で構築します。

「脳科学は科学技術の新たな世界戦略の最高峰となった。わが国の脳計画は国務院により『わが国の将来の発展...

SEO からインターネット マーケティングまで、成長しましたか?

SEOは過去2年間で大きな変化を遂げました。Baiduのアルゴリズムが何度も調整されたため、多くの人...

リンクベイティングのケーススタディ: メッセージプラグインに関する考察

コアヒント: 昨日、canonical タグについて書いたとき、外部リンクの機会について言及しました...

経験共有:B2Bウェブサイト運用アイデア(ポジショニング)

A5 Webmaster Network に「B2B ウェブサイトの運用アイデア (技術編)」という...

トラフィック価値を活性化するために、コダックとXiaomiがマーケティングの未来について議論

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています6月26日...

GoogleとBaiduの検索結果をフィルタリングする方法

中国で検索エンジンを使うのは目新しいことではありません。普通のネットユーザーの約90%は、オンライン...

個人用 Web サーバー ファイアウォール ソフトウェアのレビュー

個人のウェブマスターは非常に特殊なグループです。通常、1 人がコンピューターに向かい、Web サイト...

クラウドネイティブなデータガバナンスソリューションを設計する方法

1. 背景データ ガバナンス プロジェクトには、多くの場合、規制上の圧力、高コスト、投資収益の不明確...

2019年のデジタル中国指数レポートが発表され、クラウドの利用、GDP、デジタル経済の発展の間に強い相関関係があることが示された。

5月21日、2019年テンセントグローバルデジタルエコシステムカンファレンスが開催されました。テンセ...