序文 スタンドアロン ロックであっても分散ロックであっても、共有データに基づいて現在の操作の動作を判断するのが原則です。単一のマシンの場合、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 を学習すると、インストール後にいくつかのデフォルトのデータベースが付属していることに気付...
この記事では、Centos7.6 システムと Oracle11g を例に挙げます。 1. まずデータ...
1. はじめにこの記事では、Docker を使用して Redis を探索する方法を説明します。 Do...
<br />これは私がずっと前に集めた記事です。皆さんの参考のために共有したいと思います...
MySQL の多くのテーブルには、NULL が列のデフォルト属性であるため、アプリケーションが NU...
ページの説明: メインページ: 名前 —> shishengzuotanhuichaxun ...
ソースコードの例: https://codepen.io/shadeed/pen/03caf6b36...
目次序文1. レンダリング2. コード3. 背景画像素材要約する序文Threejs は、Web ベー...
崇高なSublime Text はコード エディター (Sublime Text2 は有料ソフトウェ...
プロジェクトのニーズにより、ブートストラップ フレームワークを慎重に学習する予定です。以前から少しは...
textarea 入力領域でテキストを折り返す場合は、<br/> と入力すると <...
目次Linux - MyCat を使用して MySQL マスター スレーブの読み取り書き込み分離を実...
問題:あるサーバー上の PHP プログラムは、localhost アドレス経由でデータベースに接続で...
目次プロジェクトの背景改善案データ特性を観察するマルチプロセスアイデアの要約データ処理スキルプロジェ...
新しいプロジェクトでは、axios によって重複した送信を防ぐことができますが、古いプロジェクト (...