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

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

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

[[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 がこれまで以上にクラウド コンピューティングを必要とする理由

推薦する

SEO最適化は評価期間中の記事コンテンツ構築の重要なポイントです - A5 Webmaster Network

皆さんご存知のとおり、新しいウェブサイトを立ち上げるときは、ウェブサイト構造の最適化、コラムの設定、...

草の根ウェブマスターの実態:厳しい生活環境と自営業の欠点

まず、感謝の意を表したいと思います。A5 ウェブサイトで私の意見を表明できることを光栄に思います。草...

FinOps: クラウドコスト管理の鍵

クラウド支出の管理がなぜ難しいのでしょうか?業界の専門家がクラウド コンピューティングの無駄に関する...

グローバル クラスター サーバー、複数の国と地域、複数の C セグメント、クリーン IP の紹介!

多くのウェブマスターは、クラスターを構築するためにクラスター サーバーを必要としており、また、Ama...

Weibo 検索は従来の検索エンジンの挑戦者となるでしょうか?

引用: 最近、新製品にもっと注目しています。製品を体験した後は、他のメディアがこの製品を別の視点から...

クラウド コンピューティング セキュリティの 3 つのレベル: 技術的リスク、管理リスク、法的リスク

クラウドコンピューティングはIT技術の分野で大きな進歩を遂げ、時代の流れをリードする新しい技術となっ...

dediserve-$5/kvm/香港/シンガポール/16 コンピュータ ルーム/1g メモリ/20g SSD/1T トラフィック/500M ポート

dediserve.com は、当初の 9 室から現在の 16 室まで、いくつかの新しいコンピュータ...

OLVPS: 生涯10%割引、3ネットワークバックホールcn2 gia、テストデータ利用可能

OLVPS (新ブランド、新商人) は、KVM 仮想 VPS を最初の 1 か月は 50% 割引、ま...

Toutiaoがついにテンセント全体を脅かし始める

2018年に売上高500億元の賭けに失敗し、多くの株式を失ったにもかかわらず、今日頭条は確かに正式な...

C2Bトレンドの台頭:カスタマイズは将来的に主流のビジネスモデルとなるか?

編集者注/ C2B(顧客対企業)モデルは、アリババグループの参謀長である曽明氏によって初めて提案され...

アマゾンとマイクロソフト、クラウドコンピューティング市場の独占調査に直面

メディア規制当局オブコムによると、アマゾンとマイクロソフトは英国のインターネット産業の70~80%を...

テンセントが「批判を求める」ため新浪微博にアカウントを開設、微博の投稿1件が12万人のフォロワーを集める

テンセントは「批判を求める」ためにSinaにWeiboアカウントを開設した(TechWebの写真)南...