序文 スタンドアロン ロックであっても分散ロックであっても、共有データに基づいて現在の操作の動作を判断するのが原則です。単一のマシンの場合、RAM メモリは共有され、クラスターの場合は、Redis、ZK、DB などのサードパーティ コンポーネントの助けを借りて実現できます。 Redis と ZK は分散ロックの優れたサポートを提供し、基本的にすぐに使用できます。ただし、これらのコンポーネント自体は高可用性である必要があり、システムもこれらのコンポーネントに大きく依存する必要があるため、余分なコストがかかります。 DB は、システムのデフォルトで高可用性コンポーネントです。DB を使用して分散ロックを実装することは、複数のマシンでのスケジュールされたタスクの起動の制御や承認コールバックの処理など、一部の低頻度のビジネスにも適したソリューションです。この記事では、DB を使用して分散ロックを実装するためのシナリオとソリューションをいくつか紹介し、皆さんの参考になれば幸いです。 テーブルデザイン まず、DB が依然としてシステムの中で最も脆弱なリンクであることは明らかです。したがって、設計時に圧力の問題を考慮する必要があります。つまり、アプリケーションで実装できるロジックは DB に実装しないでください。言い換えれば、DB が提供するロック機能はできるだけ使用しないでください。同時実行性の高いビジネスの場合は、DB ロックは避けてください。代わりに、Redis などのキャッシュ ロックを使用する方が効果的です。リスト 1 に示すように、テーブル内の唯一の制約は、lock_name、timestamp、version で構成される主キーです。これら 3 つのキーは、以下で悲観的ロックや楽観的ロックなどのビジネス シナリオを実装するために使用されます。 リスト1: 分散ロックテーブル構造 CREATE TABLE `lock` ( `lock_name` varchar(32) NOT NULL DEFAULT '' COMMENT 'ロック名', `resource` bigint(20) NOT NULL COMMENT 'ビジネス主キー', `version` int(5) NOT NULL COMMENT 'バージョン', `gmt_create` datetime NOT NULL COMMENT '生成時間', 主キー (`lock_name`,`resource`,`version`) )ENGINE=InnoDB デフォルト文字セット=utf8mb4; 悲観的ロックの実装 悲観的ロックビジネスには、次の 2 つの一般的な操作があります。 Aの場合: シナリオ A では、あるマシンがロックを取得した後、他のマシンはキュー状態になります。ロックが解除された後にのみ続行できます。このアプリケーション レベルのソリューションは非常に面倒です。そのため、通常は DB が提供する行ロック機能、つまり xxx から xxx を選択して更新する機能が使用されます。シナリオ A は、一般的に在庫の増加や減少などビジネスに密接に関連しており、ビジネス オブジェクトを行ロックとして使用できます。このソリューションのロック圧力は基本的にデータベースにかかっていることに注意してください。ブロックされているスレッドが多すぎて操作に時間がかかる場合、最終的には大量のロック タイムアウトが発生します。 Bの場合: シナリオ B (tryLock) では、特定のビジネスを例に挙げてみましょう。クラスターでは、各マシンにスケジュールされたタスクがありますが、ビジネスでは、通常、同時にスケジュールできるマシンは 1 台だけである必要があります。 スケジュールされたタスクのクリーンアップ戦略は、さらなる複雑さをもたらします。マシン A がロックを取得したが、CPU リソースの制約により、処理が遅くなったとします。このとき、スケジュールされたタスクによってロックが解除されるため、マシン B もロックを取得します。この場合、2 台のマシンが同時にロックを保持します。解決策は、タイムアウト期間をビジネス処理時間よりもはるかに長く設定するか、バージョン メカニズムを追加して楽観的ロックに変更することです。 ロックに挿入、lock_name='TaskA'、resource='ロックされたビジネス'、version=1、gmt_create=now() を設定 成功: ロックを取得します。 失敗: 操作を中止し、ロックを解除します。 楽観的ロックの実装 楽観的ロックのシナリオでは、特定のビジネスを例に挙げてみましょう。バックグラウンドシステムでは、ビジネス属性を格納するために大きなJSON拡張フィールドがよく使用されます。部分的な更新に関しては、まずそれらをクエリし、データをマージしてDBに書き込む必要があります。このプロセスに同時実行があると、データ損失が発生しやすくなります。したがって、データの一貫性を確保するためにロックが必要です。対応する操作を以下に示します。楽観的ロックの場合、デッドロックは発生しないため、ビジネスIDフィールドはここに直接保存され、各ビジネスIDに対応するレコードがあり、対応するタイマーによってクリアする必要がないことが保証されます。 select * from lock where lock_name='ビジネス名', resource='ビジネス ID'; 存在しません: ロックに挿入して、lock_name='ビジネス名'、resource='ビジネス ID'、version=1 を設定します。 バージョンを取得: バージョン ビジネス操作: データの取得、データのマージ、DB へのデータの書き戻し: update lock set version=version+1 where lock_name='business name' and resource='business id' and version= #{version}; 書き戻し成功: 操作成功 書き戻し失敗: トランザクションをロールバックしてやり直します 楽観的ロックの書き込みが失敗すると、トランザクション全体がロールバックされます。したがって、楽観的ロックは書き込み競合が頻繁に発生するシナリオには適していません。大量のトランザクション ロールバックは DB に多大な負荷をかけ、最終的には特定の業務システムに影響を及ぼします。 要約する 分散ロックの原理は実際には理解しやすいのですが、特定のビジネス シナリオに最も適したソリューションを選択する方法が難しいのです。どのロック ソリューションを使用するかに関係なく、それはビジネスと密接に関連しています。つまり、完璧な分散ロック ソリューションは存在せず、現在のビジネスに最適なロック ソリューションのみが存在するのです。 さて、今回の記事は以上です。この記事の内容が皆さんの勉強や仕事に少しでも参考になれば幸いです。123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
>>: MySQL マルチバージョン同時実行制御 MVCC の実装
MySQL バッチ挿入の問題プロジェクトを開発しているときに、古いシステムの基本データを事前にインポ...
フォーム入力ボックスの入力をdisable属性に設定して送信すると、入力ボックスの値を取得できなくな...
Ubuntu 18.04 を使用する Python 開発者向けの参考資料です。 1. Ubuntu ...
HTML5 と jQuery はアップロード前にローカル画像のプレビューを実装しており、その効果は...
最近、テスト サーバーのオペレーティング システムを Cent0S 7.5 にアップグレードし、Py...
方法1: コマンドラインの変更次の図に示すように、MySQL コンソールを開いて「set GLOBA...
需要背景チームには統合テストが必要であり、そのためには、mysql や rabbitmq などのミド...
XML/HTML コードコンテンツをクリップボードにコピー<!DOCTYPE html PUB...
サーバーに複数のサイトを展開するには、異なるサイトにアクセスするために複数のポートを開く必要がありま...
目次1. インストール2. はじめに3. 使用4. 必要に応じてEChartsチャートとコンポーネン...
この記事では、Vueの計算プロパティ実装レポートカードを参考に共有します。具体的な内容は次のとおりで...
コードをコピーコードは次のとおりです。 window.location.href="zcb...
さっそく、コードを直接投稿します。具体的なコードは次のとおりです。 <!DOCTYPE htm...
実行後、一部の Docker コンテナが終了することがあります。原因を調べるには、Docker コン...
月曜日から日曜日の時間形式の変換(Y --- 年 M --- 月 D--- 日) : : : : :...