現在、ほぼすべての大規模な Web サイトとアプリケーションは分散形式で展開されています。分散シナリオにおけるデータの一貫性の問題は常に重要なトピックです。分散 CAP 理論によれば、「分散システムは一貫性、可用性、およびパーティション耐性を同時に満たすことはできず、同時に満たすことができるのはそのうちの 2 つだけである」とされています。したがって、多くのシステムでは、設計の初期段階でこれら 3 つの間でトレードオフを行う必要があります。インターネット分野のほとんどのシナリオでは、システムの高可用性と引き換えに強力な一貫性を犠牲にする必要があります。多くの場合、最終的な時間がユーザーにとって許容可能な範囲内である限り、システムは「最終的な一貫性」を確保するだけで済みます。
多くのシナリオでは、データの最終的な一貫性を保証するために、分散トランザクションや分散ロックなど、それをサポートする多くの技術的ソリューションが必要です。場合によっては、メソッドが同じスレッドによってのみ同時に実行されるようにする必要があります。スタンドアロン環境では、Java は実際に多くの並行処理関連の API を提供しますが、これらの API は分散シナリオでは無力です。つまり、純粋な Java API では分散ロック機能を提供できません。したがって、現在、分散ロックの実装には複数のソリューションが存在します。 分散ロックの実装には、現在、次のソリューションが一般的に使用されています。
これらの実装ソリューションを分析する前に、どのような分散ロックが必要かを考えてみましょう。 (ここではメソッドロックを例に挙げていますが、リソースロックについても同様です) 分散アプリケーション クラスターでは、同じメソッドは 1 台のマシン上の 1 つのスレッドによってのみ同時に実行されることが保証されます。
データベースに基づく分散ロックの実装 データベーステーブルに基づく 分散ロックを実装するには、ロック テーブルを直接作成し、テーブル内のデータを操作して実装するのが最も簡単な方法です。 メソッドまたはリソースをロックする場合は、テーブルにレコードを追加し、ロックを解除する場合はレコードを削除します。 次のようなデータベース テーブルを作成します。
メソッドをロックしたい場合は、次の SQL を実行します。
method_name に一意の制約を設定したので、複数のリクエストが同時にデータベースに送信された場合、データベースは 1 つの操作のみが成功することを保証します。次に、正常に動作したスレッドはメソッドのロックを取得し、メソッド本体の内容を実行できると想定できます。 メソッドが実行されたときにロックを解除したい場合は、次の SQL を実行する必要があります。
上記の単純な実装には、次の問題があります。 1. このロックはデータベースの可用性に大きく依存します。データベースは単一のポイントです。データベースに障害が発生すると、ビジネス システムは利用できなくなります。 2. このロックには有効期限はありません。ロック解除操作が失敗すると、ロック レコードはデータベースに残り、他のスレッドはロックを取得できなくなります。 3. データの挿入操作では、挿入が失敗した場合にエラーが直接報告されるため、このロックは非ブロッキングのみになります。ロックを取得していないスレッドはキューに入りません。ロックを再度取得したい場合は、ロック取得操作を再度トリガーする必要があります。 4. このロックは再入不可能であり、ロックを解放する前に同じスレッドが再度ロックを取得することはできません。データは既にデータ内に存在しているからです。 もちろん、上記の問題は他の方法でも解決できます。
データベース排他ロックに基づく データ テーブル内のレコードの追加と削除に加えて、データに組み込まれたロックを使用して分散ロックを実装することもできます。 先ほど作成したデータベース テーブルも使用します。分散ロックは、データベースの排他ロックを通じて実装できます。 MySQL InnoDB エンジンに基づいて、次の方法を使用してロック操作を実装できます。
クエリ ステートメントの後に for update を追加すると、データベースはクエリ プロセス中にデータベース テーブルに排他ロックを追加します (ここで言及しておきたいのは、InnoDB エンジンがロックする場合、インデックスを検索するときにのみ行レベル ロックを使用し、それ以外の場合はテーブル レベル ロックを使用することです。ここでは行レベル ロックを使用するため、method_name にインデックスを追加する必要があります。このインデックスは一意のインデックスとして作成する必要があることに注意してください。そうしないと、複数のオーバーロードされたメソッドに同時にアクセスできないという問題が発生します。オーバーロードされたメソッドの場合は、パラメーター タイプも追加することをお勧めします)。レコードに排他ロックが追加されると、他のスレッドはレコードの行に排他ロックを追加できなくなります。 排他ロックを取得したスレッドは分散ロックも取得できると考えられます。ロックを取得した後、メソッドのビジネス ロジックを実行できます。メソッドを実行した後、次の方法でロックを解除できます。
connection.commit() 操作を通じてロックを解除します。 この方法は、前述のロックを解除できない、ロックがブロックされるといった問題を効果的に解決できます。
ただし、データベースのシングルポイントおよび再入可能性の問題を直接解決することはできません。 method_name に一意のインデックスを使用し、行レベルのロックを使用するために更新に明示的に使用していますが、ここでは別の問題がある可能性があります。ただし、MySql はクエリを最適化します。条件でインデックス フィールドが使用されている場合でも、データを取得するためにインデックスを使用するかどうかは、さまざまな実行プランのコストを判断することによって MySQL によって決定されます。 MySQL は、非常に小さなテーブルなど、テーブル全体のスキャンの方が効率的であると判断した場合、インデックスを使用しません。この場合、InnoDB は行ロックではなくテーブルロックを使用します。もしそんなことが起こったら悲劇だ。 。 。 もう 1 つの問題は、排他ロックを使用して分散ロックをロックする場合、排他ロックが長時間送信されないと、データベース接続が占有されてしまうことです。類似の接続が多すぎると、データベース接続プールが破裂する可能性があります。 要約する データベースを使用して分散ロックを実装する方法をまとめると、どちらの方法もデータベース内のテーブルに依存します。 1 つは、テーブル内のレコードの存在に基づいて現在ロックが存在するかどうかを判断することであり、もう 1 つは、データベース内の排他ロックを通じて分散ロックを実装することです。 データベースにおける分散ロックの利点 データベースに直接依存するので、理解しやすいです。 データベースにおける分散ロックの欠点 さまざまな問題が発生し、問題を解決する過程で、計画全体がますます複雑になります。 データベースを操作するには、ある程度のオーバーヘッドが必要であり、パフォーマンスの問題を考慮する必要があります。 データベースで行レベルのロックを使用することは、特にロック テーブルが大きくない場合には、必ずしも信頼できるとは限りません。 キャッシュに基づく分散ロックの実装 データベースに基づいて分散ロックを実装するソリューションと比較すると、キャッシュに基づくソリューションはパフォーマンスの点で優れています。さらに、多数のキャッシュをクラスターに展開して、単一ポイントの問題を解決することもできます。 当社には、Redis、memcached、Tair など、成熟したキャッシュ製品が数多くあります。 ここでは、Tair を例に、キャッシュを使用して分散ロックを実装するソリューションを分析します。インターネット上には Redis と memcached に関する記事が多数あり、直接使用できる成熟したフレームワークやアルゴリズムもいくつかあります。 Tair に基づく分散ロックの実装は実際には Redis に似ており、主な実装方法は TairManager.put メソッドを使用することです。
上記の実装にはいくつかの問題もあります。 1. このロックには有効期限はありません。ロック解除操作が失敗すると、ロック レコードは Tair に残り、他のスレッドはロックを取得できなくなります。 2. このロックは非ブロッキングのみが可能で、成功か失敗かに関係なく直接戻ります。 3. このロックは再入不可能です。スレッドがロックを取得した後、使用されたキーがすでに Tair に存在するため、ロックを解放する前に再度ロックを取得することはできません。 put 操作は実行できなくなりました。 もちろん、この問題を解決する方法もあります。
しかし、有効期限はどのくらいに設定すればよいのでしょうか?有効期限が短すぎると、メソッドが実行される前にロックが自動的に解除され、同時実行の問題が発生します。時間を長く設定しすぎると、ロックを取得した他のスレッドがより長い時間待機しなければならない可能性があります。この問題は、データベースを使用して分散ロックを実装する場合にも発生します。 要約する データベースの代わりにキャッシュを使用すると、分散ロックを実装でき、パフォーマンスが向上します。同時に、単一ポイントの問題を回避するために、多くのキャッシュ サービスがクラスターに展開されます。さらに、多くのキャッシュ サービスでは、Tair の put メソッドや redis の setnx メソッドなど、分散ロックを実装するために使用できるメソッドが提供されています。さらに、これらのキャッシュ サービスは、期限切れのデータの自動削除もサポートしており、タイムアウト時間を直接設定してロックの解除を制御することもできます。 キャッシュを使用して分散ロックを実装する利点 パフォーマンスが良好で実装も簡単です。 キャッシュを使用して分散ロックを実装することの欠点 ロックの有効期限をタイムアウトで制御するのはあまり信頼性が高くありません。 Zookeeper に基づく分散ロックの実装 分散ロックは、Zookeeper の一時的に順序付けられたノードに基づいて実装できます。 一般的な考え方は、各クライアントがメソッドをロックすると、ZooKeeper 上のメソッドに対応する指定されたノードのディレクトリに、一意の瞬間順序付きノードが生成されます。ロックを取得するかどうかを判断する方法は非常に簡単です。順序付けられたノード内でシーケンス番号が最小のものを決定するだけです。ロックが解除されたら、一時ノードを削除するだけです。同時に、サービスのダウンタイムによりロックを解除できないために発生するデッドロックの問題を回避できます。 Zookeeper が上記の問題を解決できるかどうか見てみましょう。
再入可能ロック サービスをカプセル化する Zookeeper サードパーティ ライブラリ Curator クライアントを直接使用できます。
Curator が提供する InterProcessMutex は分散ロックの実装です。 acquire メソッドはロックを取得するために使用され、release メソッドはロックを解放するために使用されます。 ZK を使用して実装された分散ロックは、この記事の冒頭で述べた分散ロックに対する期待をすべて完全に満たしているようです。しかし、そうではありません。 Zookeeper によって実装された分散ロックには、実際には、パフォーマンスがキャッシュ サービスほど高くない可能性があるという欠点があります。ロックの作成と解放のプロセスごとに、ロック機能を実装するために瞬間的なノードを動的に作成および破棄する必要があるためです。 ZK では、ノードの作成と削除はリーダー サーバー経由でのみ実行でき、そのデータをすべてのフォロワー マシンで共有することはできません。 実際、Zookeeper を使用すると同時実行の問題が発生する可能性もありますが、これは一般的ではありません。次の状況を考えてみましょう。ネットワーク ジッターにより、クライアントと ZK クラスター間のセッション接続が切断されます。その後、ZK はクライアントが切断したと判断し、一時ノードを削除します。このとき、他のクライアントは分散ロックを取得できます。同時実行の問題が発生する可能性があります。 zk には再試行メカニズムがあるため、この問題は一般的ではありません。 zk クラスターがクライアントのハートビートを検出できない場合は、再試行します。 Curator クライアントは複数の再試行戦略をサポートしています。一時ノードは、複数回の再試行後に失敗した場合にのみ削除されます。 (したがって、適切な再試行戦略を選択し、ロックの粒度と同時実行性のバランスを見つけることも重要です。) 要約する Zookeeperを使用して分散ロックを実装する利点 単一点問題、非再入問題、非ブロッキング問題、ロックを解除できない問題を効果的に解決します。実装は比較的簡単です。 Zookeeperを使用して分散ロックを実装することの欠点 パフォーマンスは、キャッシュを使用して分散ロックを実装する場合ほど良くありません。 ZK の原則をある程度理解している必要があります。 3つのソリューションの比較 上記のいずれの方法でも***を達成できません。 CAP と同様に、複雑さ、信頼性、パフォーマンスなどの要件を同時に満たすことは不可能です。したがって、最善の方法は、さまざまなアプリケーション シナリオに応じて最も適切なものを選択することです。 理解の難しさの観点から(低い順から高い順) データベース > キャッシュ > Zookeeper 実装の複雑さの観点から(低から高) Zookeeper >= キャッシュ > データベース パフォーマンスの観点から(高から低) キャッシュ > Zookeeper >= データベース 信頼性の観点から(高から低) Zookeeper > キャッシュ > データベース [この記事は、51CTOコラムニストのホリス、著者WeChatパブリックアカウントホリス(ID:hollischuang)によるオリジナル記事です] この著者の他の記事を読むにはここをクリックしてください |
<<: BitCloudは産業用ソフトウェアのデジタル配信を加速します
>>: Zang Chengwei: レスポンシブアーキテクチャの実践に基づく Meituan Dianping のクライアント
ウェブサイト編集者は、ウェブサイトの全体的なコンテンツとメインスタイルを作成します。ウェブサイトが訪...
インタラクティブプロトタイプは、製品開発プロセスにおける重要な出力です。製品のプレゼンテーション形式...
filemedia は 2008 年に設立されたドイツのホスティング サービス プロバイダーです。現...
11月26日のAdmin5 Webmaster Networkによると、山東インターネットウェブマス...
LFCHOSTING は 1996 年に設立されたホスティング会社です。その事業には、仮想ホスティン...
みなさんこんにちは。私は湖南省出身のキネスです。今回は、編集者が新しいウェブサイトを最適化し、短期間...
資金が少しある多くの企業が百度プロモーションを行っています。百度プロモーションは確かに短期間で成果を...
調査によると、エンタープライズ ハイブリッド クラウド環境に導入されるサーバー、ディスク ストレージ...
holderhost.com の openvz 用大容量メモリ VPS をご紹介します。サーバー構成...
広告に多額の費用を費やしたのに、なぜ成果が見られないのでしょうか?ユーザーは来たのになぜ買わないので...
ugvps ブラックフライデーセール 月額 4.99 ドル、2G メモリ、100M サーバー帯域幅、...
この記事を始める前に、まず明確にしておきたいのは、Google は長い間世界トップクラスのドメイン名...
中国インターネット情報センターの報告によると、2014年12月現在、中国のインターネット利用者数は6...
[要約] 秘密権使用者の特徴は、若く、教養が高く、活力があり、新しいものを好むことです。彼らは家にこ...
最近、みんなが知乎を開く衝動は何でしょうか?ソウルジョークの作者たちは次のように答えた。知乎といえば...