最近、分散トランザクション、分散フレームワーク、ZooKeeper、SpringCloud など、分散に関する問題が広く言及されるようになりました。この記事では、まずロックの概念を確認し、次に分散ロックを紹介し、Redis で分散ロックを実装する方法について説明します。 1. ロックの基礎知識まず、私たちの仕事と研究におけるロックの概念を見直してみましょう。 なぜ最初にロックについて説明し、次に分散ロックについて説明しなければならないのでしょうか? ロックの役割は、共有リソースへのマルチスレッド アクセスによって発生するスレッド セーフティの問題を解決することであることは誰もが知っています。しかし、日常生活で鍵はあまり使われません。ロックの概念や基本的な使用法についてよくわかっていない友人もいるかもしれませんので、まずロックについて説明し、次に分散ロックについて詳しく説明します。
チケット販売の小さな例を見てみましょう。たとえば、全員が dota2 ti9 のチケットを入手しようとした場合、チケットがロックされていないとどのような問題が発生するでしょうか?この時点でコードは次のようになります。
コード分析: ここには 8 つの ti9 チケットがあり、同時にチケットを取得するために 10 個のスレッド (つまり、10 人のユーザーをシミュレート) が設定されています。グラブが成功した場合は成功と表示され、失敗した場合は失敗と表示されます。当然ながら、8 人がゲームを奪取することに成功し、2 人が失敗したはずです。実行結果を見てみましょう: 実行結果は期待と一致しないことがわかりました。 10 人全員がチケットを購入したため、スレッド セーフティの問題が発生したことになります。それで、何が原因だったのでしょうか? 理由は、複数のスレッド間に時間差があるためです。 図に示すように、残っているチケットは 1 つだけですが、両方のスレッドによって読み取られた残りのチケットは 1 です。これは、スレッド A が在庫を変更する前に、スレッド B がチケットを正常に取得したことを意味します。
操作結果: 予想通り、2名がチケットを入手できませんでした。我々の目標は達成されたようだ。 2. ロックパフォーマンスの最適化2.1 ロック保持時間を短縮する 実際、私たちの日常生活の理解によれば、ジム全体で運動している人が 1 人だけということはあり得ません。したがって、1 台のマシンをロックするだけで済みます。たとえば、1 人がランニングをしているときに、もう 1 人は他のスポーツを行うことができます。 チケットシステムの場合、在庫変更操作のコードをロックするだけで済みます。他のコードは引き続き並行して実行できるため、ロック保持時間が大幅に短縮されます。コードは次のように変更されます。
確かに、コードの一部だけをロックすると、コードの実行効率が大幅に向上します。 したがって、スレッドの安全性の問題を解決した後、ロック後のコード実行効率も考慮する必要があります。 2.2 ロックの粒度を下げる たとえば、最近公開された映画には『哨戒班』と『スパイダーマン』の 2 つがあります。支払い購入プロセスをシミュレートし、メソッドを待機させて、CountDownLatch の await メソッドを追加します。実行結果は次のとおりです。
実行結果: 悪魔少年ネザの残り投票数: 20 Nezha チケットの購入時にブロックすると、Spiderman チケットの購入に影響することが判明しました。実際、これら 2 つのムービーは互いに独立しているため、ロックの粒度を下げて、ムービー オブジェクト全体のロックを 2 つのグローバル変数のロックに変更する必要があります。変更されたコードは次のとおりです。
実行結果: 悪魔少年ネザの残り投票数: 20 スパイダーマンの残り投票数: 100 これで、2 つの映画のチケットを購入しても、お互いに影響がなくなります。これはロックを最適化する 2 番目の方法であり、ロックの粒度を減らします。ちなみに、Java 並行性パッケージの ConcurrentHashMap は、大きなロックを 16 個の小さなロックに変換し、セグメント化されたロックを通じて効率的な並行安全性を実現します。 2.3 ロックの分離 ロック分離は、一般的に読み取り/書き込み分離と呼ばれます。ロックは読み取りロックと書き込みロックに分けられます。読み取りロックはブロックする必要はありませんが、書き込みロックでは同時実行の問題を考慮する必要があります。 3. ロックの種類
ここでは、各タイプのロックの概念を一つ一つ説明することはしません。自分で学ぶこともできます。ロックは、バイアスロック、軽量ロック、重量ロックに分類することもできます。 4. Redis 分散ロックロックとロックの最適化の基本的な概念を理解した後、分散ロックの概念について詳しく説明します。 上の図は私たちが構築した分散環境を示しています。チケット購入アイテムは 3 つあり、1 つのインベントリに対応します。各システムには複数のスレッドがあります。上記の通り、在庫変更操作はロックされています。これら 6 つのスレッドのスレッド セーフティは保証できますか? もちろん違います。各チケット購入システムにはそれぞれ独立した JVM プロセスがあるため、同期を追加しても 1 つのシステムのスレッドの安全性は保証されますが、分散スレッドの安全性は保証されません。 したがって、この問題を解決するには、3 つのシステムすべてに共通するミドルウェアが必要です。 ここでは、分散ロックとして Redis を選択します。複数のシステムが Redis に同じキーを設定します。設定は、キーが存在しない場合にのみ成功し、キーはいずれかのシステムの一意の識別子に対応します。システムがリソースへのアクセスを終了すると、キーは削除され、ロックを解除する目的が達成されます。 4.1 分散ロックで注意すべきこと 1) 相互排他性 一度にロックを取得できるのは 1 つのクライアントのみです。 これは理解しやすいですね。すべてのシステムのうち 1 つのシステムだけがロックを保持できます。 2) デッドロック防止 クライアントがロックを保持したままクラッシュし、ロックを解放しない場合、他のクライアントはロックを取得できず、デッドロックが発生します。したがって、クライアントがロックを解除することを確認する必要があります。 Redis では、デッドロックが発生しないようにロックの有効期限を設定できます。 3) ロックホルダーでロックを解除する ベルを結んだ人が、それを解く必要があります。システムのロックとロック解除には同じクライアントを使用する必要があります。クライアント A のスレッドによって追加されたロックは、クライアント A のスレッドによってロック解除される必要があります。クライアントは別のクライアントのロックを解除できません。 4) 再入性 クライアントがオブジェクト ロックを取得した後、クライアントはオブジェクトのロックを再度取得できます。 4.2 Redis分散ロックプロセス Redis 分散ロックの具体的なプロセス: 1) まず、Redis キャッシュのプロパティを使用して、Redis にキーと値のペアを設定します。キーはロックの名前です。すると、クライアントの複数のスレッドがロックを競い合うことになります。競争が成功した場合、値はクライアントの一意の識別子に設定されます。 2) ロックを競合するクライアントは、次の 2 つのことを行う必要があります。
有効期間の長さは、ビジネスニーズに基づいて継続的なストレステストを通じて決定する必要があります。
したがって、ここでの値は一意の識別子 (uuid など) に設定されます。 3) 共有リソースにアクセスする 4) ロックを解除します。ロックを解除する方法は2つあります。 1 つ目は、有効期間が経過すると自動的にロックを解除することです。 2 番目は、一意の識別子に基づいて、ロックを解除する権限があるかどうかを最初に判断することです。識別子が正しい場合、ロックは解除されます。 4.3 ロックとロック解除 4.3.1 ロック 1) setnx コマンド ロック 存在しない場合は設定します。Redis コマンド setnx を使用します。 setnx の意味は、ロックが存在しない場合にのみロックが正常に設定されるということです。 2) デッドロックを防ぐためにロックの有効期間を設定します。 ロックには 2 つの手順が必要です。何か問題が起きないか考えてみませんか? ロック後にクライアントが突然クラッシュしたらどうなりますか?そうすると、ロックは有効期間のないロックとなり、デッドロックが発生する可能性があります。これが起こる可能性は非常に低いですが、問題が発生すると非常に深刻なので、これら 2 つの手順を 1 つにまとめる必要があります。 幸いなことに、Redis 3.0 ではこれら 2 つの命令が 1 つの新しい命令に統合されました。 Jedis の公式ドキュメントのソースコードを見てみましょう。
これが私たちが望んでいるものです! 4.3.2 ロック解除
ロック解除も 2 段階のプロセスであり、ロック解除の原子性も確保され、2 つの手順が 1 つに結合される必要があります。 これは Redis では実現できず、Lua スクリプトでのみ実現できます。
これは、ロックを保持しているかどうかを判定し、ロックを解除する Lua スクリプトです。 Lua スクリプトがアトミックなのはなぜですか? Lua スクリプトは eval() 関数を使用して jedis によって実行されるため、実行されると完全に実行されます。 5. Redis分散ロックコードの実装
6. 分散ロックの比較6.1 データベースベースの分散ロック 1) 実装 ロックを取得するときにデータを挿入し、ロックを解除するときにデータを削除します。 2) デメリット
6.2 Zookeeper に基づく分散ロック 1) 実装 ロックすると、指定されたノードのディレクトリに新しいノードが作成され、ロックが解除されるとこの一時ノードは削除されます。ハートビート検出機能があるため、デッドロックが発生せず、より安全です。 2) デメリット パフォーマンスは平均的で、Redis ほど効率的ではありません。 それで:
七。結論この記事では、ロックの基本概念から始め、複数のスレッドが共有リソースにアクセスするときに発生する可能性のあるスレッド セーフティの問題を提案し、次にロックを追加することでスレッド セーフティの問題を解決します。この方法ではパフォーマンスが低下するため、ロック保持時間の短縮、ロック粒度の低減、ロックの分離という 3 つの方法でロックを最適化する必要があります。 次に、分散ロックの 4 つの特性について説明します。
その後、Redis を使用して分散ロックを実装しました。ロックには Redis コマンドが使用され、ロック解除時のアトミック性を保証するために Lua スクリプトが使用されました。 最後に、3 つの分散ロックの利点、欠点、および使用シナリオを比較します。 分散ロックについて新たな理解が得られ、問題解決を検討する際にはパフォーマンスの問題についてさらに深く考えるようになることを願っています。 [この記事は51CTOコラムYiXin Technology Institute、WeChatパブリックアカウント「YiXin Technology Institute(id:CE_TECH)」からのオリジナル記事です] この著者の他の記事を読むにはここをクリックしてください |
<<: クラウドユーザーがデータベース開発を振り返る 2019年クラウドコンピューティングソフトウェアレビュー
>>: Java プログラムでよく使用されるメモリ モジュールは何ですか?
Naiyun の最新の中秋節と国慶節特別オファーが始まりました: クラウド サーバーの月額支払いは ...
昨日、Linode は、最低 VPS 価格を 1G メモリで月額 5 ドルに引き下げると発表しました...
世界中で金融テクノロジーのブームが起こっており、新たな「競争相手」の出現により、従来の金融機関は大き...
クラウド コンピューティング業界は 10 年以上前から存在しており、インターネットに代表される爆発的...
新しいウェブサイトの診断と分析には、一般的に 2 つの状況があります。1 つは新しいウェブサイトの運...
2014年9月3日、百度世界大会で、百度は長らく計画していた大きな動きであるダイレクトナンバーパブリ...
最適化担当者にとって、自社サイトを最適化する場合でも、サイトの最適化を依頼する場合でも、開始する前に...
1月10日、中国情報通信研究院(以下、「CAICT」)が主催し、クラウドコンピューティング標準およ...
月収10万元の起業の夢を実現するミニプログラム起業支援プランこのような包括的で完璧なユーザー エクス...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますキーワード...
6 月のブラック ストームは、多くのウェブマスターの友人を「悲痛な思い」にさせたに違いありません。当...
突然の感染症の発生により、デジタル化は生活、仕事、社会活動の統治にとって「必須の選択肢」であるだけで...
solarvps を購入しました。無駄のないプローブ: http://65.181.116.152:...
12月24日には、3月にVipshopが赤字で上場、5月にテンセントの電子商取引事業が独立、8月にグ...
alpha1servers は 2011 年に設立され、その VPS の価格は常にかなり手頃です。K...