ロックの詳細な分散

データベースに基づいて:

 

データベーステーブルに基づいて、分散ロックの楽観的ロックを行います。(版) 

 

(更新用のInnoDB)悲観的ロックを行うためにデータベーステーブルに基づいて

 

データレコードに基づいて制約(テーブルに記録されているメソッド名)のデータベーステーブルのみを行います

 

ベースのキャッシュ:

 

分散ロック用のRedisのSETNX()を使用。(SETNX、現在提供直接タイムアウト時間+保持動作の不可分の値)

 

memcachedのadd()メソッド、分散ロックを使用します。

 

PUT()メソッド、分散ロックを使用してTAIR。

 

ベースの飼育係:

 

ロック方法の各クライアントは、飼育係法上のノードに対応する指定されたディレクトリが瞬時順序付けられた固有のノードを生成します。 

 

ロックのみ順序付けノードを取得するかどうかを決定する最小数を決定します。ロックが解除された場合は、単にこのノードを削除することは、瞬間することができます。

 

分散データベース・ロックの実装に基づいて、

 

データレコードに基づいて制約(テーブルに記録されているメソッド名)のデータベーステーブルのみを行います

 

分散ロック、可能性は直接ロックテーブルを作成することです最も簡単な方法を達成するために、表の操作中のデータにより実現。

 

我々は方法やリソースのいずれかをロックするときは、このレコードを削除するには、ロックを解除したい場合、我々は、テーブル内のレコードを追加することができます。このようなデータベーステーブルを作成:

 

 

 

 

私たちは、特定のメソッドをロックしたい場合は、以下のSQLを実行します。

 

 

 

 

我々は同時にデータベースに提出複数の要求がある場合、データベースは1つの操作のみが(アトミック)成功できることを保証しますMETHOD_NAME、上の唯一の制約をしたので、我々は成功し、そのスレッドをとることができる方法を取得して動作しますロックは、メソッド本体の内容を実行することができます。

メソッドが終了すると、私たちは、ロックを解除したい場合、あなたは、次のSQLを実行する必要があります。

 

 

 

 

上記のこの単純な実現は、以下の質問があります。

 

1は、ロックは、データベースの可用性に強く依存している、データベースは、データベースがハングアップしたら、システムはサービスが使用不能に原因となります、単一のポイントです。

 

2は、ロックはロック解除操作が失敗したら、それはロックがデータベースに記録されていると、他のスレッドが再ロックを取得することはできませんつながる、何の有効期限はありません。

 

図3は、ロックは、データ挿入動作は、直接挿入するエラーが一度失敗し、非ブロックであってもよいです。スレッドがロックを取得しないと、再びロックを獲得するためにトリガーをロックし、再び軌道に乗るために、キューキューに入りません。

 

4、ロックが非リエントラントでロックが解除されていない前に、同じスレッドが再びロックを取得することはできません。データ内のデータがすでに存在するため。

 

もちろん、我々はまた、上記課題を解決する他の方法を持つことができます。

 

  • データベースは、単一のポイントですか?前に二つのデータベース、双方向のデータ同期に従事。ハングアップしたらすぐにバックアップリポジトリに切り替えます。

     

  • 故障までの時間がありませんか?ただ、再びデータベースのタイムアウトでデータをクリーンアップするために、定期的に定期的な仕事をします。

     

  • ノンブロッキング?挿入成功リターン成功するまで、whileループに従事。

     

  • 非リエントラント?データベーステーブルと2つのフィールド、レコードの現在のホスト情報とマシンのロックを取得するための情報をスレッドで、他のレコード数再入国、あなたがロックを取得次回最初のクエリのデータベース、場合のカウント値がデータベース内の現在のホストマシンとスレッドの情報についての情報は、直接それをロックするために彼を割り当て、見つけることができ、そしてカウントがインクリメントされます。レコードは削除することができたときにカウント値が0であるとき、ロックが解除されたときにカウント値が1だけ減算されます。

     

(UPDATEステートメントのためのInnoDBエンジン)悲観的ロックを行うためにデータベーステーブルに基づいて

 

削除データテーブルにより、より記録動作に加えて、データが実際に分散ロックを達成するためのロック手段を来ることができます。また、テーブルが作成したばかり行くデータベースを使用します。分散ロックは、データベースに排他ロックを介して達成することができます。MySQLのInnoDBエンジンに基づいて、ロック操作は、以下の方法を用いて実施することができます。

 

クエリ後に更新のために増やし、データベースは、クエリ時にデータベーステーブルの排他ロックに増加します(这里再多提一句,InnoDB引擎在加锁的时候,只有通过索引进行检索的时候才会使用行级锁,否则会使用表级锁。这里我们希望使用行级锁,就要给method_name添加索引,值得注意的是,这个索引一定要创建成唯一索引,否则会出现多个重载方法之间无法同时被访问的问题。重载方法的话建议把参数类型也加上)

 

レコードは排他ロックを追加すると、他のスレッドは、もはや排他ロックを高めるためにライン上に記録することはできません。私たちは、その後、以下の方法でアンロック、メソッドの実行後に、ビジネス・ロジック・メソッドを実行することができ、ロックが取得されたときに排他ロックのスレッドは、分散ロックを取得することができます取得すると考えることができます:

 

公共ボイドロック(){

Connection.setAutoCommit(偽)

int型のカウント= 0;

ながら(カウント<4){

{試します

ロックlock_name = xxxの更新のためのSELECT * FROM。

{(結果がnullでない)場合

//代表がロックしてもらいます

返します。

}

}キャッチ(例外e){

 

}

// nullまたはまったくロックを言わなかったことを得るそして、例外をスロー

スリープ(1000);

++数えます。

}

新しいLockExceptionを投げます();

}

 

Connection.commit()操作でロックを解除するには。

 

効果的に問題を解決することができ、この方法では、上記のロックとブロッキング・ロックを解放することはできません。

 

  • ロックをブロックしますか?UPDATE文のためにそれが成功するまでの失敗を実行すると、ブロックされた状態にあった実行が成功し、直後に戻ります。

  • サービスをロックダウンした後、解放することができませんか?このように、データベースサービスのダウンタイムの後に解放されたロックを所有します

     

しかし、まだ単一のポイントと直接データベースリエントラントの問題を解決することはできません。

 

行レベルのロックを使用するように更新し、表示のために使用する、我々はMETHOD_NAMEに一意のインデックスを使用しているが、別の問題があるがあってもよいです。しかし、MySQLのクエリがさえた状態でのインデックスフィールドで、最適化されますが、のようなMySQLの全表スキャンがより高い効率を考えるならば、様々な実施計画のコストを決定することによって決定されるのMySQLからデータを取得するためにインデックスを使用するかどうかいくつかの小さなテーブルは、その代わりに行ロックの使用のInnoDBテーブルロックこの場合には、インデックスを使用しないであろう。この悲劇は起こった場合。

 

もう一つの問題は、我々は、データベース接続を取るだろうし、長い時間のための排他ロックは、提出しない分散型ロックを行ロックのロックを使用したいということです。接続が類似になった後は、データベース接続プールが爆発することができるようすることができます

 

分散ロックのためのデータベース・リソース・テーブルに基づいて、楽観的ロックの操作を行います。

 

1.まず、楽観的ロックの意味:

 

 ほとんどは、達成するための記録メカニズムのデータバージョン(VERSION)に基づいています。どのようなデータのバージョン番号?データは、データベーステーブルのバージョンベースのソリューションは、一般に、データベーステーブルの「バージョン」フィールドを追加することによって、データを読み出す際に、更新後、一緒にこのバージョンを読んで達成することが、バージョン識別子の付加でありますこのバージョン番号はインクリメントされます。

バージョン番号と一致しない場合、更新は失敗し、更新時に、バージョン番号は、それが正常にこの操作を実行する、それが一貫している場合、変更されていない、比較します。

 

2.私たちの次は我々が対処すべきかを推測するために、具体的な例と組み合わせて、楽観的ロックの意味の一定の理解を持っています:

 

  • 6つのフィールドID、RESOOURCE、STATE、ADD_TIME、UPDATE_TIME、それぞれVERSION、主キー、リソース割当状態(1、2が割り当てられた割り当てられていない)、リソースを有するT_RESOURCEを、以下に示すように、我々は、リソーステーブルがあるとし作成時間、リソースは、リソースデータのバージョン番号を更新しました。

     

  • 私たちは今、その後、非分散型ケースのシナリオは、我々は一般的にSTATE = 1(未割り当て)データをチェックアウトした後、文によって実行することができ、そこからのデータのいずれかを選択するために、ID = 5780このデータ配信を、我々を仮定します更新が成功した場合、それは、このリソースの更新T_RESOURCE SET STATE = 2 STATE = 1、ID = 5780を占領しました。

     

  • データベース更新原子の操作に分散シナリオは、原子である場合は、実際には、理論的にはこの文の上、問題はありませんが、典型的な「ABA」でこのif文、我々は知覚することはできません。一つは、「ABA」の問題が何であるかを尋ねるかもしれませんか?あなたがここに、インターネット上で検索することができます私はあなたの第一及び第二の更新プロセスを選択した場合、二つの動作が非アトミックであるため、単純なポイントは、と言うので、一つのスレッドがある場合は、このプロセスは、最初のリソースを占有しますその後、(STATE = 2)、およびリソース(STATE = 1)をリリース、あなたが実際にUPDATE操作を実行する最後の時間は、これはリソースの変更が起こったかを知る方法はありません。おそらく、あなたは、あなたが言ったシーンで大丈夫であることを言うだろうが、そのようなプロセスで銀行口座の預金やデビットなど実際の使用で、この状況はもっと恐ろしいです。

     

  • だから、あなたはどのように我々はそれの上に問題を解決しないロック楽観使用している場合は?

     

  現在のデータのクエリデータのバージョン番号からA.まずSELECTは、現在のバージョン番号などのデータが26です。

  ID、RESOURCE、STATE、STATE = 1、ID = 5780 T_RESOURCEからバージョンを選択します。

  B.実装のアップデート:

  UPDATE T_RESOUREセット状態= 2、VERSION = 27、UPDATE_TIME = NOW()RESOURCE = XXXXXX AND 

  STATE = 1とバージョン= 26

  C.上記のステートメントが真UPDATE更新、データの一つの行に影響を与えた場合は、プレースホルダの成功を示しています。あなたはデータの影響を受けた1行を更新しない場合は、リソースが他の人を占有されています。

 

3.楽観的ロックのデータベーステーブルに基づいていくつかの欠点を行います。

 

(1)この動作モードでは、元の更新動作の一は、第2の動作にならなければならない:バージョン番号を選択し、UPDATE一度。データベース操作の数を増やします。

 

ビジネス・プロセスのビジネスシーンを、より多くのリソースは、データの整合性を確保するために必要な場合は楽観的ロック・テーブルを使用して、すべてのリソースベースのデータベース場合には、各リソースはリソーステーブルを持っているように、(2)、そして、それはこれが必要であり、実際の使用では、シーンは確かに満足していません。これらは、データベース操作に基づいており、高い同時実行性の要件の下で、データベース接続のコストは耐え難いでなければなりません。

 

(3)。楽観的ロック機構は、多くの場合、論理データ・ストレージ・システムに基づいており、したがってダーティデータがデータベースに更新させてもよいです。システム設計段階では、我々は完全に考慮に生じるこれらの状況の可能性を取り、そしてそのようなだけこのストアドプロシージャの更新経路外利用可能なデータに基づいて、データベースのストアドプロシージャに実装楽観的ロック戦略ではなく、データベースのような適切な調整を行う必要があります公衆に直接開いているテーブル。

 

私たちは楽観的ロックの実装と短所について話しました、そしてそれをロック楽観感じることを恐れていないのですか?もちろんそうではない、資料の冒頭に私自身のビジネスシナリオ、シナリオ1と2オプティミスティック・ロック・データベース・リソース・テーブルの使用に基づいてシーンの一部であり、オンラインの問題に良い解決策を持っています。良いプログラムは、だから我々は選択の技術的な解決策に応じて、特定のビジネスシナリオでなければならない、単なるビジネス上の問題に十分に複雑な十分なトレンディな技術ソリューションを見つけることではないでしょうか?私はシーンにいる場合たとえば、私は飼育係のロックを使用して行う、あなたはそう、本当に必要なことができますか?必要はありません答え!

 

一つは、現在そこにラッチされているかどうかを決定するために、テーブル内のレコードが存在することで、これらの2つの方法は、データベース内のテーブルに依存しているロックを使用して分散データベースを実装する方法を要約すると、他のデータベースを介してです分散ロックを実装するための排他ロック。

 

分散データベースロックの利点を実現

    直接データベースを経由して、簡単に理解します。

 

分散データベース・欠点・ロックの実装

    全体のスキームが複雑になるになるだろうな問題を解決する過程で、さまざまな問題があります。

    データベースの操作は、検討する特定のコスト、パフォーマンスの問題が必要です。

    データベース行レベルロックを使用すると、私たちは、テーブルに大きな時間をロックしていない場合は特に、必ずしもトリッキーではありません。

 

分散ロックのRedisベースのキャッシュの実装

 

分散ロック用のRedisのSETNX()を使用。(不可分)

 

キーが存在しない場合にのみ場合SETNXは、キー値の値に設定されています。指定されたキーがすでに存在する場合、SETNXは何もしません。

 

•プロセスがロックを取得することを示し、1を返し、SETNXは、キーの値は、現在の時刻+有効時間プラスロックをロックするように設定されたタイムアウトをlock.id。

•ロックが他のプロセスによって得られたことを示す、0を返し、プロセスがクリティカル領域を入力することはできません。プロセスがロックを取得するためにSETNXがループで動作しようとし続けることができます。

 

問題のデッドロック

 

SETNXは、分散ロックを達成するため、デッドロック状態があるかもしれません。スタンドアローンモードでのロックと比較すると、分散環境だけでなく、我々はまた、プロセスとロックの間でネットワークを考慮する必要があり、プロセスが表示されていることを確認する必要があります。スレッドはRedisのからロック、切断を取得した後、ロックが他のスレッドをロックします競争は、ハングデッドロック状態を作り出す、時間内に解除されません。したがって、この場合にはロック・タイムアウトを取得する必要があり、すなわちsetExpire、自動的にロック・タイムアウトをリリース

 

ベースの飼育係を実現する分散ロック

 

分散ロック・飼育係の一時的な順序ノードを達成することができます。

 

これは、一般的な考え方です。

 

ロック方法の各クライアントは、飼育係法上のノードに対応する指定されたディレクトリは、一意の一時命じたノードを生成します。ロックを取得するかどうかを決定することは非常に簡単であり、順序付けられたノードの最小限決意番号を必要とします。 

 

ロックが解除されると、これだけの一時的なノードを削除することができます。同時に、ノード自体にキューノードは、前の行をリッスンする必要があるので、ノードが解放されたときにコールバック通知を受信することができ、ロックを取得することができました。クライアント管理により、セッションのZKは、それが解放することができないロックによって引き起こされるサービスのダウンタイムを回避することができ、そして得られたデッドロックは、ロック・タイムアウトは注意を必要としません。

 

飼育係を見て、上記の問題を解決することはできません。

 

  • ロックを解除することができないのですか?使用飼育係は、効果的にロックを作成するときに、クライアントが突然ロック(切断されたセッションを)ハングアップしたようになったら、クライアントは、一時的なノードZKを作成するためのロックの問題は、その後、一時的に解放することはできません解決することができますノードは自動的に削除されます。他のクライアントは再びロックを取得することができます。

     

  • ロックをノンブロッキング?飼育係は、クライアントは、ノードの順にZKを作成することができ、ブロッキングロックを使用して、ノード上のリスナーをバインド達成することができ、ノードの変更は一度、飼育係がクライアントに通知されます、ノードを確認することができ、クライアントは、自分が現行のものではありません作成します、自身がロックを取得するのであれば、最小数のすべてのノードは、あなたがビジネスロジックを実行することができます。

     

  • 非リエントラント?効果的に、クライアント・ノードの作成、ホスト情報と、現在のクライアントスレッド情報はノード、あなたがロックし、現在の最小ノードを取得したい次回に直接書き込まれる再入国の問題を解決することはできません飼育係を使用している場合以上のデータは、それをクリックしてください。あなたとあなたの情報と同じ場合には、自身が直接ロックに、場合にも、同じではないとして、キューに関与するノードの一時的な順序を作成します。

     

  • シングルポイントの問題?使用飼育係は、効果的に、我々はサービスを提供することができ、単一のポイントの問題は、ZKが生き残るためには、クラスタ内のマシンの半分以上である限り、クラスタにデプロイされて解決することができます。

     

サードパーティのライブラリのキュレーターの飼育係のクライアントとして使用することができ、クライアントは再入可能ロックサービスをカプセル化します。

 

InterProcessMutexキュレーターオファーが分散ロックを達成することです。ロックを解除するためのロック解除プロセスを取得するための取得ユーザの方法。

 

ZKは、分散ロックを使用して実装完全にこの資料の冒頭に沿って、分散ロックのためのすべての我々の期待のようです。しかし、実際には、ない、飼育係分散ロックは欠点が実際に存在している実感します那就是性能上可能并没有缓存服务那么高作成中に毎回そのため、動的に作成され、ロックを達成するための過渡ノードを破壊され、中にロックを解放します。ZK作成および削除ノードが唯一のリーダーサーバによって実行することができ、そのデータは、すべてのフォロワーマシンに同期されます。

 

実際には、飼育係の使用は、並行性の問題をもたらすことも可能であるが、それは一般的ではありません。その後、クライアントがハングアップすることをZK、原因ネットワークジッタに、クライアント・セッションZKクラスタ接続が切断され、ケースを考えてみましょう、それは、他のクライアントは、分散ロックを取得することができ、この時間は、一時的なノードを削除します。同時実行の問題が生じる可能性があります。再試行メカニズムのZK、クライアントのハートビート一度検出不可能なZKクラスタは、それが再試行されます、キュレーターのクライアントが複数の再試行戦略をサポートしているため、この問題は一般的ではありません。それでも、複数の再試行の後に動作しない場合、一時的なノードを削除します。(だから、適した再試行戦略を選択すると、ロックの粒度と同時実行の間のバランスを見つけることも重要です。)

 

プログラムのZKベースの概要

 

飼育係分散ロックを使用することの利点が達成されます。

シングルポイントの効果的な解決策ではなく、リエントラント問題は、非ブロックロックの問題や課題を解除することができません。実装が比較的簡単。

 

欠点を実現飼育係分散ロックを使用します

パフォーマンスの向上のロックを達成するための分散キャッシュを使用します。私たちは、ZKの原理を理解する必要があります。

 

三つの比較

完璧にすることはできません方法でいくつかの方法で、上記の。同様に、CAP好きなので、自分自身のために最も適したを選択し、複雑性、信頼性、パフォーマンスなどの面で同時に満たすことができないことは、異なるアプリケーションのシナリオに応じて、王です。

 

理解しやすさの観点(低から高へ)から

データベース>キャッシュ>飼育係

 

実装の観点から(低い順に)複雑

飼育係> =キャッシュ>データベース

 

パフォーマンスの観点から(安いものから高いものへ)

キャッシュ>飼育係> =データベース

 

信頼性の観点から(低いものから高いものへ)

飼育係>キャッシュ>データベース

 

おすすめ

転載: www.cnblogs.com/minikobe/p/11578437.html