序文 スタンドアロン ロックであっても分散ロックであっても、共有データに基づいて現在の操作の動作を判断するのが原則です。単一のマシンの場合、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 の実装
textarea の形式は保存時にデータベースに保存できますが、表示時には /n と相互に変換できな...
リーダーの指示のもと、Java プロジェクトを引き継ぎ、リファクタリングを行う必要がありました。同時...
目次1. ランダムなブール値( true / false )を取得する2. 指定された日付が営業日で...
原因: NVIDIA グラフィック カード ドライバーが破損している解決:コマンドラインモードで再起...
目次問題の説明フロントエンド制御(方法1)アイデアコードバックエンド制御(方法2)アイデアコード要約...
方法1: var a = [1,2,3]; var b = [4,5] b を連結します。 コンソー...
目次【効果】 【実施方法】 【効果】 【実施方法】 <テンプレート> <div i...
適応型レイアウトは、実際のアプリケーションでますます一般的になっています。今日は、主にフローティング...
ngx_lua_module は、lua パーサーを nginx に埋め込み、lua 言語で記述され...
今日は、CentOS 6.8 サーバーに MySQL 8.0.18 をインストールする方法を記録しま...
この記事の例では、ショッピングカートのロジックと機能を実装するためのjsの具体的なコードを共有してい...
まず、どのフィールドまたはフィールドの組み合わせがデータ行を一意に識別できるかを決定する必要がありま...
水平方向では、テーブルの配置を左、中央、右に設定できます。基本的な構文<テーブル配置=&quo...
1. ソースコードの設計コードをコピーコードは次のとおりです。 <!DOCTYPE html ...
1. 空のディレクトリを作成する $ cd /home/xm6f/dev $ mkdir myapp...