上司から分散ロックについて質問されたのですが、結果は悲惨なものでした...

上司から分散ロックについて質問されたのですが、結果は悲惨なものでした...

会社は新人のシャオユアンに、分散ロックの使用を必要とする、シャオユアンにとって難しい、輝かしい困難なプロジェクトを与えました。

[[321687]]

画像はPexelsより

分散ロックが素晴らしいということだけは聞いたことがありますが、他のことは何も知りません。まあ、わからなかったら聞けばいいので、上司にアドバイスを求めました。

上司:分散ロックは毎日経験しているのではないでしょうか?思い出させてあげましょう。

小園:さて、メロンの種まきベンチの準備ができました。

この記事は次のように構成されています。

  • 分散ロックを使用する理由は何ですか?
  • 分散ロックの特徴は何ですか?
  • 分散ロックの一般的なアルゴリズムとその利点と欠点
  • 要約する

分散ロックを使用する理由は何ですか?

この質問は次の 2 つの質問に分割する必要があります。

①なぜロックを使うのか?

共有リソースに一度にアクセスできるのは 1 つのクライアントのみであることを確認します。ロックの目的に応じて、次の2つのタイプに分けられます。

  • 共有リソースを操作できるのは1つのクライアントのみ
  • 共有リソースにより複数のクライアントが操作可能

アクセスが許可されるのは 1 つのクライアントのみです。共有リソースに対する操作はべき等ではありません。データの変更および削除操作でよく使用されます。

上記の例では、

複数のクライアントが操作できるようにする: 主なアプリケーション シナリオは、データ クエリなど、共有リソースに対する操作がべき等であることです。

これらすべてがべき等性を持っているのに、なぜ分散ロックが必要なのでしょうか?通常、これは繰り返しの操作(特にリソースを消費する操作)を回避するための効率性またはパフォーマンスのためです。

たとえば、一般的なキャッシュ スキームは次のとおりです。

上記の例では、

ここでのリソースはべき等であるため、通常はキャッシュされます。これは一般的なロック + キャッシュ アーキテクチャです。

これは、次のような、より多くのリソース (時間、メモリ、CPU など) を消費するべき等リソースを取得するためによく使用されます。

  • ユーザー情報の照会
  • 過去の注文を照会する

もちろん、リソースが特定の期間内にのみべき等である場合は、アーキテクチャをアップグレードする必要があります。

ロック + キャッシュ + キャッシュ無効化/無効化再取得/キャッシュ時間指定更新。

②なぜロックを分散させる必要があるのか​​?

上記のキャッシュ ソリューションを引き続き例として取り上げますが、ここでは若干の変更を加えます。

上記の例では、

分散ロックの特徴は何ですか?

① 相互排他性

一度にロックを取得できるのは 1 つのクライアントのみです。

PS: 複数のクライアントが同時にロックを取得できる場合、ロックは無意味になり、共有リソースのセキュリティは保証されません。

上司:会議室でクライアント A を迎えると、他のクライアントは待たなければなりません。私のオフィスに他の人を連れてくるには、私が空くまで待つ必要があります。

小園:分かりました。

受信クライアント(非べき等共有リソース)ボスが解放されるまで待ちます(ロックを取得します)。

②再入性

クライアント A はロックを取得し、ロックの有効期限が切れない限りロックを取得し続けることができます。鍵は私と一緒にあります。これからも使い続けます。他の人がそれを取ることは許可されていません。

この機能は、[ロック更新]機能を適切にサポートできます。たとえば、クライアント A がロックを取得し、ロックの解放時間は 10 秒です。 10S の有効期限が切れそうになったとき、クライアント A はタスクを完了していないため、別の 5S を申請する必要があります。ロックが再入可能でない場合、クライアント A はロックを更新できず、その結果、ロックが他のクライアントに奪われることになります。

小園:それは学びました。ボス、3分後に次の面接があります。

上司:シャオユアン、君がそんなに学ぶ意欲があるのは珍しいね。とても嬉しいです。コミュニケーション時間を 10 分延長し、他の会議を延期しましょう。

③高性能

ロックを取得する効率は十分に高い必要があります。ロックの取得でビジネスがブロックされるわけにはいきませんよね?

Xiaoyuan: わかりました。DingTalk で会議を 10 分延長する申請をしました。

上司: そうですね、私は会議の招待を承諾しました。

小元:ボス、あなたは本当に有能ですね。

④高可用性

分散型マイクロサービス環境では、サービスの高可用性を保証する必要があります。そうしないと、最悪の場合、他のビジネス モジュールに影響が及ぶ可能性があり、さらにはサービス アバランシェが発生する可能性もあります。

上司:私の携帯電話は24時間オンになっています。会議中に私に連絡が取れない場合は、秘書に連絡してください。

⑤ブロッキングロックとノンブロッキングロックをサポート

ロックの取得に失敗した場合、システムは直接失敗を返す必要がありますか、それともロックが正常に取得されるまでブロックする必要がありますか?ビジネスシナリオが異なれば答えも異なります。

例えば:

⑥権限のロックを解除する

クライアントは、自身が追加したロックのみを解除(ロック解除)できます。一般的な解決策は、ロックに乱数 (または ThreadID) を追加することです。

ボス:シャオユアン、ここまで話したけど、全部理解できたかな?

檻の中のオウム:分かりました。わかりました。

ボス:黙れ、私は小元に尋ねているんだ、小元自身だけが答える資格があるんだ。

⑦デッドロックを回避する

ロック側が異常終了し、ロックを積極的に解除できない。一般的な方法は、ロックするときにタイムアウトを設定することです。ロックがアクティブに解除されない場合、Redis の自動有効期限を使用してロックがパッシブに解除されます。

秘書が飛び込んできてこう言った。「ボス、10分間の会議は終了です。」隣の李さんはもう待てない。

上司:時間を忘れました。李さんに会いに行かなければなりません。

小園: ボス、まだ話が終わってませんよ…

⑧例外処理

一般的な異常な状況には、Redis のダウンタイム、クロックジャンプ、ネットワーク障害などがあります。

小元:何が起こっても、私は鍵を手に入れることはできないでしょう。どうすればいいですか?

PS: これは複雑なので、特定のビジネス シナリオに基づいて分析する必要があります。同期的に処理する必要があるサービスの場合、障害アラームを発行する必要があります。遅延処理が可能なサービスの場合は、他のシステムで処理するために障害情報を記録することを検討できます。

分散ロックの人気アルゴリズム

ベーシックプラン SETNX

ロックは、Redis SETNX 命令に基づいて取得されます。

①ロックを取得する SET lock: resource_name random_value NX PX 30000

lock: resource_name: リソース名、ロックされたオブジェクトの一意の識別子。

random_value: 通常は、「UUID+ThreadID」などのロッカーの一意のタグを格納します。

NX: この機能はキーが存在しない場合にのみ設定され、つまり、他の人によってロックされていない場合にのみロックをロックできます。

PX: ロックタイムアウト。

もちろん、このロック方法は「ロックの再入」をサポートしていません。

②ロックを解除する(LUAスクリプト)

checkValueThenDelete: ロック解除側がロック側であるかどうかを確認します。そうであれば、ロック解除は許可されます。そうでない場合、ロック解除は許可されません。

疑似コードは次のとおりです。

  1. パブリッククラスRedisTool {
  2. // ロックを正常に解除しました
  3. プライベート静的最終Long RELEASE_LOCK_SUCCESS = 1L;
  4.  
  5. /**
  6. * 分散ロックを解除する
  7. *
  8. * @param jedis Redisクライアント
  9. * @param lockKey ロックマーク
  10. * @param lockValue ロック値
  11. * @returnリリースが成功したかどうか
  12. */
  13. 公共 静的ブール型 releaseDistributedLock(Jedis jedis, String lockKey, String lockValue) {
  14. 文字列スクリプト = "" +
  15. 「redis.call('get', KEYS[1]) == ARGV[1]の場合」 +
  16. "redis.call('del', KEYS[1]) を返す " +
  17. 「その他」 +
  18. " 0 を返す " +
  19. "終わり" ;
  20. // Collections.singletonList(): メモリ割り当てを減らすために要素が 1 つだけのシナリオで使用されます
  21. オブジェクト結果 = jedis.eval(script、Collections.singletonList(lockKey)、Collections.singletonList(lockValue));
  22. (RELEASE_LOCK_SUCCESS.equals(結果)) の場合 {
  23. 戻る 真実;
  24. }
  25. 戻る 間違い;
  26. }
  27. }

レッドロックアルゴリズム

このアルゴリズムは、分散シナリオでのロック実装ソリューションとして、Redis の作者 antirez によって提案されました。

Redlock アルゴリズムの原理: [コア] ほとんどのノードがロックを正常に取得し、ロックは有効のままです。

ステップ 1: 現在の時刻 (ミリ秒単位) を取得します。

ステップ 2: N 個の Redis ノードから順番にロックを取得します。ランダム文字列 random_value を設定します。ロックの有効期限を設定します。

  • 注 1: ロックを取得するときはタイムアウトを設定する必要があります (ノードが使用できなくなるのを防ぐため)。タイムアウトはロックの有効期間 (数十ミリ秒) よりもはるかに小さくする必要があります。
  • 注 2: ノードがロックの取得に失敗すると、すぐに次のノードからロックを取得します (ノードのロックがすでに他のクライアントによって保持されている場合など、あらゆるタイプの障害)。

ステップ 3: ロックを取得するのにかかる合計時間を計算します。

ステップ 4: ロックが正常に取得されました。

ロックを正常に取得しました: クライアントは大多数のノード (>=N/2+1) からロックを正常に取得し、totalTime はロックの有効期間を超えません。

ロックの有効期間を再計算します。つまり、初期ロックの有効期間から、ロックを取得するためにかかった時間の 3.1 倍を差し引きます。

ステップ 5: ロックの取得に失敗しました。

取得に失敗した場合は、[すべての]クライアントに対してロック解除 (Lua スクリプト) を直ちに開始する必要があります。

ステップ6: ロックを解除します。

業務が完了したら、直ちに [すべての] クライアントに対してロック解除 (Lua スクリプト) を開始する必要があります。

Redlock アルゴリズムの利点:

  • 高可用性とは、ほとんどのノードが正常であることを意味します。
  • フェイルオーバー中に単一の Redis ノードの分散ロックで発生するロック失敗の問題はなくなりました。

Redlock アルゴリズムの問​​題点:

  • Redis ノードのクラッシュはロックのセキュリティに影響します。ノードがクラッシュするまでロックは保持されず、ノードが再起動するとロックは失われます。 Redis のデフォルトの AOF 永続性では、1 秒ごとにディスクをフラッシュ (fsync) しますが、最悪の場合、1 秒分のデータが失われます。
  • 絶え間ないジャンプを回避するには、管理者が手動でクロックを変更します。 [システムクロックを調整しない] ntpd (クロック同期) プログラムを使用し、複数回の微調整を通じてクロックを変更します。
  • クライアントがブロックするとロックが期限切れになり、共有リソースが安全でなくなります。
  • ロックの取得に時間がかかり、有効期間が非常に短くなる場合、ロックをすぐに解除する必要がありますか?どのくらいの長さが短いとみなされますか?

フェンシングトークンを使用した実装

分散システムの専門家である Martin Kleppmann 氏は、RedLock のセキュリティ問題について議論し、問題を提起しました。

神々の戦い: Martin Kleppmann 氏は、Redis の作者 antirez 氏が提案した RedLock アルゴリズムにはセキュリティ上の問題があると考えており、両者はインターネット上で何度も議論と対立を重ねてきました。

Martin 氏は、RedLock アルゴリズムの中心的な問題は次の通りであると指摘しました。

  • ロックの有効期限切れまたはネットワークの遅延により、ロックの競合が発生します。クライアント A のプロセスが一時停止 → ロックの有効期限が切れる → クライアント B がロックを保持する → クライアント A が再開し、共有リソースへの書き込み要求を開始します。ネットワーク遅延でも同様の効果が生じます。
  • RedLock セキュリティはシステム クロックに大きく依存します。

フェンシングトークンアルゴリズムの原理:

  • フェンシング トークンは単調に増加する数値であり、クライアントがロックを正常に取得すると、ロックとともにクライアントに返されます。
  • クライアントは共有リソースにアクセスするときにトークンを持ち込みます。
  • 共有リソース サービスはトークンをチェックし、遅延した要求を拒否します。

フェンシング トークン アルゴリズムの問​​題:

  • 共有リソース サービスを変革する必要があります。
  • リソース サービスも分散されている場合、複数のリソース サービス ノードでトークンが確実に増加されるようにするにはどうすればよいでしょうか。
  • 2 つのフェンシング トークンがリソース サービスに到着する順序が逆になり、サービス チェックが異常になります。
  • 【antirez】リソースへの相互排他アクセスを維持するためのフェンシングメカニズムがあるのに、なぜ分散ロックが必要で、強力なセキュリティが必要なのでしょうか?

その他の分散ロック

データベース排他ロック:

  • ロックを取得します (更新用に選択、悲観的ロック)。
  • ビジネス ロジックを処理します。
  • ロックを解除します (connection.commit())。

注: InnoDB エンジンがロックする場合、インデックスを介して取得するときにのみ行レベルのロックが使用され、それ以外の場合はテーブルレベルのロックが使用されます。したがって、lock_name はインデックス化される必要があります。

ZooKeeper 分散ロック:

  • クライアントは znode ノードを作成し、作成が成功するとロックが正常に取得されます。
  • ロックを保持しているクライアントは、共有リソースへのアクセスを完了すると znode を削除します。
  • znode は一時的なものとして作成されるため (znode 機能)、znode を作成したクライアントがクラッシュした場合に znode が自動的に削除されます。
  • [質問] Zookeeper はクライアントと Zookeeper サーバーに基づいてセッションを維持し、セッションの維持には定期的なハートビートに依存しています。

Zookeeper が長時間クライアントのハートビートを受信できない場合、タスク セッションは期限切れになり、このセッションによって作成されたすべての一時的な znode ノードが削除されます。

Google の Chubby 分散ロック:

  • シーケンサー メカニズム (フェンシング トークンに類似) は、遅延によって発生する問題を軽減します。
  • ロック所有者はいつでもシーケンサーを要求できます。
  • クライアントがリソースを操作すると、シーケンサーがリソース サーバーに渡されます。
  • リソースサーバーはシーケンサーの有効性をチェックします。① Chubby の API (CheckSequencer) を呼び出してチェックします。 ② クライアントとリソースサーバーが現在観測しているシーケンサー(フェンシングトークンのようなもの)を比較して確認します。 ③lock-delay: クライアントがロックを保持するためのロック遅延時間を指定できるようにします。 Chubby は、クライアントが接続を失ったことを検出すると、ロック遅延時間内にロックを取得するために他のクライアントを編成します。

要約する

どのような分散ロックアルゴリズムを使用すればよいでしょうか?

  • テクノロジーはすべてビジネス目的のためであり、「ハイエンド」な見せかけの選択は避けてください。
  • ビジネス シナリオに応じて、可能な限り最もシンプルなアプローチを選択します。
  • 最も単純な分散ロックによって時々発生する例外に対処するにはどうすればよいでしょうか?ビジネスの正確性を確保するには、追加のメカニズムや手動介入を追加することをお勧めします。通常、この部分のコストは、複雑な分散ロックの開発および運用保守コストよりも低くなります。

分散ロックを操作するもう 1 つの方法である「分割統治」は、永続的です。

  • 共有リソース自体を分割できる場合は、個別に処理します。
  • たとえば、電子商取引システムでは、過剰販売を防ぐために、10,000 枚のマスクがすぐに売り切れてしまうとします。従来のアプローチでは、ロックを使用してすべてのリソースを制御します。もう 1 つのプレイ方法は、20 個のロックを使用して 10,000 個のマスクを制御することです。これにより、全体的なパフォーマンスが瞬時に数十倍向上します。

追記:ここでの過剰販売は単なる一例です。実際のシナリオでの売り過ぎはより複雑なので、注意が必要です。

<<:  実行中の Kubernetes ポッドにパッチを適用するにはどうすればよいでしょうか?

>>:  NHS がこれまで以上にクラウド コンピューティングを必要とする理由

推薦する

グループ購入モデルをどのように革新すれば、収益性を高め、投資を引き付けることができるでしょうか?

2011 年に急成長を遂げた後、共同購入 Web サイトは 2012 年に重要な時期を迎えました。現...

探索は喜びと不安をもたらす

Google の「ロボット」がインターネットの隅々までクロールして以来、検索エンジンは人々にとって欠...

主流のプロモーションチャネルのインベントリと分析、1000万のプロモーション費用の使い方を教える

どのプロモーション チャネルがより効果的かとよく聞かれます。現在、複数のチャネルで同時にプロモーショ...

リスク管理を活用して、小紅書が棚から撤去されるのを防ぐにはどうすればよいでしょうか?

01最近、ネット界で一番ホットな出来事は、小紅書が店頭から撤去されたことだ。 7月29日夕方、小紅書...

simplydigitalhosting-256m メモリ KVM/11g SSD/800g トラフィック/月額 5.61 ドル

Simplydigitalhosting は 2011 年末に設立されました。主な事業には、cpan...

デジタル経済の展望に関する白書

「デジタル経済白書」は​​、アナリシスがデジタル経済の各業界で培った経験とデータの蓄積を凝縮し、デジ...

スマートホストはどうですか?ソルトレイクシティ (ユタ州 - 米国) VPS レビュー

スマートホストはどうですか?スマートホストは良いですか? Smarthost は、米国西部のソルトレ...

Cloudive-2GメモリKVM月額7ドル

Cloudive はトルコに登録された会社で、米国イリノイ州ロンバードに KVM ベースの 40G ...

「クラウドコンピューティング」は現在、「フォグコンピューティング」は未来?

過去 10 年間のテクノロジーにおける最大のトレンドの 1 つは、企業間でクラウド コンピューティン...

ウェブマスターは頻繁に更新される Baidu アルゴリズムにどのように対処するのでしょうか?

最近の百度アルゴリズムのアップデートにより、多くのウェブマスターの友人が百度の非人道性について不満を...

Baidu は、Web サイトにブラック ハット SEO 行為があるかどうかをどのように判断しますか?

Baidu は、Web サイトにブラック ハット SEO 行為があるかどうかをどのように判断しますか...

マイクロソフトのハリー・シャム氏:過去を振り返り、新しいことを学び、責任感を持ってイノベーションを推進する

本日、烏鎮で開催されている世界インターネット会議において、多くの同僚と「過去を振り返り新たなことを学...

100万人の開発者にサービスを提供し、Tencent Cloudネイティブ製品API呼び出しは1日あたり100億回を超える

テンセントクラウドの劉宇紅副社長は7月31日、2020年クラウドネイティブテクノロジーカンファレンス...

MLMウェブサイトが禁止されているにもかかわらず、依然として人気がある理由:報告、証拠収集、調査が難しい

Jinqiao.comホームページのスクリーンショット「毎月2人を雇えば、1年後には月収が少なくとも...

最大vps-64mメモリKVM簡易評価

つい最近、Hostcat に maximumvps に関する記事が掲載されました (maximumv...