序文前回の記事では、eコマース シナリオでのフラッシュ セールの例を通じて、モノリシック アーキテクチャでロックを使用する方法を紹介しました。ただし、現在では多くのアプリケーション システムが非常に大規模になっており、多くのアプリケーション システムはマイクロサービス アーキテクチャ システムです。では、このクロス JVM シナリオでは、並行性をどのように解決すればよいのでしょうか。 モノリシック アプリケーション ロックの制限実際の実践に入る前に、インターネット システムのアーキテクチャの進化について簡単にお話ししたいと思います。 インターネット システムの開発当初は、リソースの消費量は比較的少なく、ユーザー数も比較的少なかったため、ニーズを満たすには 1 つの Tomcat アプリケーションを展開するだけで済みました。 Tomcat を JVM プロセスと見なすことができます。大量のリクエストが同時にシステムに到着すると、すべてのリクエストがこの 1 つの Tomcat に送られます。前の記事で説明したフラッシュ セールや在庫削減のシナリオなど、一部のリクエスト メソッドをロックする必要がある場合、この Tomcat はニーズを満たすことができます。しかし、アクセス数が増えてくると、1台のTomcatでは対応しきれなくなります。このとき、Tomcatをクラスターにデプロイし、複数のTomcatでシステムをサポートする必要があります。 上図の単純な進化の後、システムを共同でサポートするために 2 つの Tomcat を展開します。リクエストがシステムに到着すると、まず nginx を通過します。nginx はロード バランサとして機能し、独自のロード バランシング構成戦略に従って、リクエストをいずれかの tomcat に転送します。多数のリクエストが同時にアクセスされた場合、2 つの Tomcat がすべてのトラフィックを共有します。この後、在庫を減らすためにフラッシュセールを実施する場合、単一のアプリケーションロックを使用して需要を満たすことはできますか? 先ほど追加したロックは、JDK が提供するロックです。このロックは単一の JVM で動作します。2 台以上ある場合、大量の同時リクエストが異なる Tomcat に分散されます。各 Tomcat では同時実行を防ぐことができます。ただし、複数の Tomcat 間では、各 Tomcat のロック取得リクエストによって、再び同時実行が発生します。したがって、在庫を減算するという問題は依然として存在します。これは単一アプリケーション ロックの制限です。では、この問題をどう解決すればよいのでしょうか?次に、分散ロックについて説明します。 分散ロック分散ロックとは何ですか?では、分散ロックとは何でしょうか? 分散ロックについて説明する前に、単一アプリケーション ロックの特徴は、1 つの JVM 内では有効ですが、複数の JVM やプロセス間では有効ではないという点であることがわかります。したがって、あまり公式ではない定義をすることができます。分散ロックとは、複数の JVM と複数のプロセスにまたがるロックです。このようなロックが分散ロックです。 デザインのアイデア Tomcat は Java によって起動されるため、各 Tomcat は JVM と見なすことができ、JVM 内のロックは複数のプロセスにまたがることはできません。したがって、分散ロックを実装する場合は、これらの JVM の外部でそれらを探し、他のコンポーネントを通じて実装することしかできません。 上の図では、2 つの Tomcat がサードパーティ コンポーネントを使用して、JVM 間およびプロセス間の分散ロックを実装しています。これは分散ロックのソリューションです。 実装では、これを実現するために現在利用できるサードパーティ コンポーネントは何でしょうか?より人気のあるものは次のとおりです。
上記の実装方法については、Lao Mao が具体的なコード例を通じて 1 つずつ実演しています。 データベースに基づく分散ロックアイデア: 主に更新に select ... を使用して、データベース悲観的ロックに基づく分散ロックを実装します。 select ... for update の目的は、クエリ中にクエリされたデータをロックすることです。ユーザーがこの種の操作を実行すると、他のスレッドはデータを変更または削除できなくなります。他のスレッドは、前のスレッドが操作を完了して解放するまで待機してから操作を続行する必要があります。これにより、ロックの効果が得られます。 実装: 電子商取引における過剰販売の例に基づいてコードを共有します。 前回のモノリシック アーキテクチャのオーバーセリングの例を使って、皆さんと共有しましょう。前回のコードを修正し、distribute_lock という新しいテーブルを作成します。このテーブルの主な目的は、データベース ロックを提供することです。このテーブルの状況を見てみましょう。 売られ過ぎ注文のシナリオをシミュレートしているため、上図の注文のロック データがあります。 前の記事のコードを変更してコントローラーを抽出し、Postman を介して呼び出しを要求します。もちろん、ポート 8080 とポート 8081 の 2 つの JVM がバックグラウンドで起動されて動作します。完成したコードは次のとおりです。 /** * @著者 [email protected] * @日付 2021/1/3 10:48 * @desc 公開アカウント「プログラマーおじさん」 */ @サービス 翻訳者 パブリッククラスMySQLOrderService { @リソース プライベート KdOrderMapper orderMapper; @リソース プライベート KdOrderItemMapper orderItemMapper; @リソース プライベート KdProductMapper productMapper; @リソース プライベートDistributeLockMapperdistributeLockMapper; //購入商品ID プライベート int 購入製品 ID = 100100; //購入商品の数量 private int purchaseProductNum = 1; @Transactional(伝播 = 伝播.REQUIRED) パブリックInteger createOrder()は例外をスローします{ log.info("メソッドを入力しました"); DistributeLock ロック = distributorLockMapper.selectDistributeLock("order"); if(lock == null) throw new Exception("このビジネスの分散ロックは構成されていません"); log.info("ロックを取得しました"); //ここでは、並行性を手動で実証するために 1 分間スリープします。Thread.sleep(60000); KdProduct 製品 = productMapper.selectByPrimaryKey(purchaseProductId); if (product==null){ 新しい例外をスローします("購入製品: "+purchaseProductId+" は存在しません"); } //商品の現在の在庫 Integer currentCount = product.getCount(); log.info(Thread.currentThread().getName()+"在庫数"+currentCount); //在庫を確認する if (purchaseProductNum > currentCount) { throw new Exception("Product"+purchaseProductId+" には "+currentCount+" 個のアイテムしか残っていないため、購入できません"); } //データベース内の削減操作を完了します。productMapper.updateProductCount(purchaseProductNum,"kd",new Date(),product.getId()); // 順序を生成... 回数は省略されています。ソースコードは Lao Mao の github からダウンロードできます: https://github.com/maoba/kd-distribute order.getId() を返します。 } } SQL は次のように記述されます。 選択 * 配布ロックから ここで、business_code = #{business_code,jdbcType=VARCHAR} 更新用 上記が主な実装ロジックです。コード内の以下の点に注意してください。
最終的な実行効果を見てみましょう。まず、コンソール ログを確認します。 8080 のコンソール ログは次のとおりです。
8081 のコンソール ログは次のとおりです。
ログから、2 つの異なる JVM の 8080 への最初のリクエストが最初にロックを取得し、8081 へのリクエストは実行前にロックが解放されるのを待機していることがわかります。これは、分散ロックが効果的であることを示しています。 8080のリクエスト:
8081 のリクエスト:
明らかに、2 番目のリクエストは在庫不足のため失敗しました。もちろん、このシナリオは当社の通常のビジネス シナリオと一致しています。最終的に、データベースは次のようになります。 当然ながら、このデータベースにある在庫と注文数量も正確です。この時点で、データベースに基づく分散ロックの実践的なデモンストレーションは完了です。このタイプのロックを使用する利点と欠点をまとめてみましょう。
最後に前述のデータベース分散ロックについては、実際のところ、日常の開発ではほとんど使用されていません。より一般的に使用されているのは、Redis と ZK ベースのロックです。本来、この記事では Redis ロックと ZK ロックを一緒に共有したかったのですが、同じ記事に書くと長くなりすぎるため、この記事ではこのタイプの分散ロックについて共有します。ソースコードはLao MaoのGitHubからダウンロードできます。アドレスは https://github.com/maoba/kd-distribute です。 MySQL が実際に分散ロックを実装する方法についてのこの記事はこれで終わりです。MySQL 分散ロックに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: TCPソケットSYNキューとAcceptキューの差異分析
>>: HTML テーブル マークアップ チュートリアル (30): セルの暗い境界線の色属性 BORDERCOLORDARK
この記事では、Spring boot + Maven プロジェクトのデプロイメントを例に、Code ...
序文:私は友人のプロジェクトのバグを修正するのを手伝ったのでこれを書きました。この関数を書くのは初め...
序文通常、ファイル内の特定の行を削除したい場合は、まずファイルを開き、削除する内容を見つけて、これら...
最近、ネイティブ JS を使用して、さらにいくつかの小さな機能を実装したいと思っています。現在、ブロ...
1. まず、VS2019とMySQLデータベースを準備します。どちらも公式サイトからダウンロードで...
1. 設置環境Windows7 で MySQL5.6 データベースの解凍バージョンをアンインストー...
序文MySQL を扱ったことがある人なら、テーブル メタデータ ロックの待機についてよく知っているは...
この記事の例では、グラフィック検証コードを実装するためのVueプロジェクトの具体的なコードを参考まで...
docker における実行と開始の違いDocker run はミラーイメージを指定します。そしてdo...
環境の紹介: Ubuntu Server 16.04.2+MySQL 5.7.17 コミュニティ サ...
概要: 2 つの MySQL SQL ステートメント ロックの分析次のSQL文にどのようなロックが追...
Linux に触れたばかりの方には、この内容が役に立つかもしれません。Linux にしばらく触れてい...
JavaScript スクリプトは HTML 内のどこにでも埋め込むことができますが、いつ呼び出され...
1. Python 3をインストールする1. 依存パッケージをインストールしますyum instal...
この記事は MySQL 公式サイトを参考にしてまとめたものであり、遭遇したいくつかの問題も記録されて...