導入分散システムやマイクロサービス アーキテクチャが普及している今日の世界では、サービス間の呼び出しの失敗は当たり前のことになっています。例外をどのように処理するか、データの一貫性をどのように確保するかは、マイクロサービスの設計プロセスでは避けられない難しい問題になっています。 ビジネスシナリオが異なれば、ソリューションも異なります。一般的な方法は次のとおりです。
この記事では、他のいくつかの項目に焦点を当てています。 2PC および 3PC の従来の取引については、すでにオンラインで多くの情報が公開されているため、ここでは繰り返しません。 再試行をブロックするマイクロサービス アーキテクチャでは、再試行をブロックすることが一般的な方法です。 疑似コードの例:
上記のように、サービス B への API リクエストが失敗すると、最大 3 回の再試行が開始されます。 3 回失敗すると、ログを出力して実行を継続するか、上位層にエラーをスローします。 このアプローチでは、次のような問題が発生します。
最初の問題は、サービス B の API がべき等性をサポートするようにすることで解決できます。 2 番目の問題: バックグラウンドのタイミング手順を通じてデータを修正できますが、これは適切な解決策ではありません。 3 番目の質問: これは、再試行をブロックすることで一貫性と可用性を向上させるために避けられない犠牲です。 再試行のブロックは、ビジネスが一貫性の要件に敏感でないシナリオに適しています。データの一貫性が求められる場合は、問題を解決するために追加のメカニズムを導入する必要があります。 非同期キューソリューションの進化のプロセスでは、キューを導入することが一般的で、より優れた方法です。次の例:
現在のサービスがデータを DB に書き込んだ後、メッセージを MQ にプッシュし、独立したサービスが MQ を消費してビジネス ロジックを処理します。ブロッキング再試行と比較すると、MQ は通常のビジネス サービスよりもはるかに安定していますが、ネットワークの問題、現在のサービス停止などにより、MQ にメッセージをプッシュする呼び出しが失敗する可能性が依然としてあります。この場合も、ブロッキング再試行と同じ問題が発生します。つまり、DB 書き込みは成功しますが、プッシュは失敗します。 理論的に言えば、分散システムでは、複数のサービス呼び出しを伴うコードでは必ずこのような状況が発生し、長期的には呼び出しの失敗が確実に発生します。これも分散システム設計における難しさの 1 つです。さらに、MQ シリーズのインタビューの質問と回答がすべて整理されています。 WeChat で Java テクノロジー スタックを検索し、バックグラウンドで「インタビュー」を送信してオンラインで読むことができます。 TCC 報酬業務トランザクションの要件があり、分離が不便な場合は、TCC 補償トランザクションを選択する方がよいでしょう。 TCC は各サービス コールを 2 つの段階と 3 つの操作に分割します。
TCC では、各サービスに上記の 3 つの操作用の API を実装する必要があります。サービスが TCC トランザクションにアクセスする前は 1 回の呼び出しで完了していた操作は、2 段階、3 つの操作で完了する必要があります。 たとえば、ショッピング モール アプリケーションでは、次の疑似コードに示すように、A 在庫サービス、B 金額サービス、C ポイント サービスを呼び出す必要があります。
コードは、A、B、C サービス API を呼び出して、リソースをチェックおよび予約します。すべてが成功を返すと、確認操作が送信されます。 C サービスの Try 操作が失敗した場合、A、B、C の Cancel API が呼び出され、予約済みのリソースが解放されます。 TCC は、分散システム内の複数のサービスと複数のデータベースにわたるデータの一貫性の問題を解決します。ただし、TCC 方式には、上記のセクションで説明した通話障害など、実際の使用時に注意する必要がある問題がまだいくつかあります。 空のリリース上記のコードでは、C.Try() が実際に失敗した場合、以下の冗長な C.Cancel() 呼び出しによってリソースは解放されますが、ロックはされません。これは、現在のサービスでは、呼び出しの失敗によって実際に C リソースがロックされたかどうかを判断できないためです。呼び出されない場合、実際には成功しますが、ネットワーク上の理由により失敗が返され、C のリソースがロックされ、解放されなくなります。 実稼働環境では空のリリースが頻繁に発生します。 TCC トランザクション API を実装する場合、サービスは空のリリースの実行をサポートする必要があります。 タイミング上記のコードでは、C.Try() が失敗すると、C.Cancel() が呼び出されます。ネットワーク上の理由により、C.Cancel() 要求が最初に C サービスに到着し、C.Try() 要求が後に到着する可能性があります。これにより、空の解放問題が発生し、C のリソースがロックされて解放されなくなります。 したがって、C サービスはリソースを解放した後、Try() 操作を拒否する必要があります。具体的な実装では、一意のトランザクション ID を使用して、最初の Try() とリリース後の Try() を区別できます。 通話に失敗しました一般的なネットワーク上の理由などにより、呼び出しプロセス中にキャンセルと確認が失敗する場合があります。 Cancel() または Confirm() 操作が失敗すると、リソースがロックされ、解放されなくなります。この状況に対する一般的な解決策は次のとおりです。
理論的には、2 つの非アトミック コード セグメントとトランザクション コード セグメントに中間状態が存在し、中間状態の存在は障害が発生する可能性があることを意味します。 ローカルメッセージテーブルローカル メッセージ テーブルはもともと eBay によって提案されました。ローカル メッセージ テーブルとビジネス データ テーブルを同じデータベースに配置できるため、トランザクション特性を満たすためにローカル トランザクションを使用できます。 具体的なアプローチは、ローカル トランザクションにビジネス データを挿入するときにメッセージ データを挿入することです。その後、後続の操作を実行します。他の操作が成功した場合は、メッセージを削除します。失敗した場合は、メッセージを削除せず、非同期でメッセージをリッスンして再試行を続けます。 ローカル メッセージ テーブルは優れたアイデアであり、さまざまな方法で使用できます。 MQと協力する擬似コードの例:
上記のコードでは、messageTxSql はローカル メッセージ テーブルに挿入される SQL ステートメントです。
これはビジネス SQL と同じトランザクションで実行され、成功するか失敗します。 成功した場合はキューにプッシュされます。プッシュが成功した場合は、messageTx.Cancel() を呼び出してローカル メッセージを削除します。プッシュが失敗した場合は、メッセージを確認済みとしてマークします。ローカル メッセージ テーブルのステータスには、試行と確認の 2 つの状態があります。どのような状態であっても、OnMessage はそれを監視し、再試行を開始できます。 ローカル トランザクションにより、メッセージとサービスがデータベースに書き込まれることが保証されます。その後は、ダウンタイムやネットワーク プッシュの失敗に関係なく、非同期監視によって後続の処理が実行され、メッセージが MQ にプッシュされることが保証されます。 MQ は、消費者サービスに到達することを保証します。 MQ の QOS 戦略を使用すると、コンシューマー サービスはトランザクションを処理するか、次のビジネス キューに引き続き配信できるため、トランザクションの整合性が確保されます。 サービスコールに協力する 擬似コードの例:
これは、MQ を導入せずに、ローカル メッセージ テーブル + 他のサービスを呼び出す例です。この方法は、非同期再試行とローカル メッセージ テーブルを使用してメッセージの信頼性を確保し、再試行のブロックによって発生する問題を解決し、日常の開発でより一般的になっています。 DB に書き込むローカル操作がない場合は、ローカル メッセージ テーブルにのみ書き込み、OnMessage で処理することもできます。
メッセージの有効期限ローカル メッセージ テーブルの Try および Confirm メッセージ ハンドラーを構成します。
メッセージ処理機能では、現在のメッセージ タスクに時間がかかりすぎているかどうかを判断する必要があります。たとえば、1 時間再試行してもまだ失敗する場合は、電子メール、テキスト メッセージ、ログ アラームなどを送信して手動介入を可能にすることを検討してください。
Try 処理機能では、Try 状態のメッセージは作成されたばかりで、まだ確認、送信、または削除されていない可能性があるため、現在のメッセージ タスクが短すぎるかどうかを判断する必要もあります。これにより、通常のビジネス ロジックの実行が繰り返され、成功した呼び出しも再試行されます。この状況をできるだけ回避するには、メッセージの作成時間が非常に短いかどうかを検出します。もしそうなら、スキップできます。 再試行メカニズムは、ビジネス ロジックの観点から、必然的に下流 API のべき等性に依存します。処理しないことも可能ですが、通常のリクエストに干渉しないように設計する必要があります。さらに、Java コア テクノロジーのチュートリアルとサンプル ソース コードも推奨されます: https://github.com/javastacks/javastack 独立したメッセージングサービス独立メッセージ サービスは、ローカル メッセージ テーブルを独立したサービスに抽出する、ローカル メッセージ テーブルのアップグレード バージョンです。すべての操作の前に、メッセージ サービスにメッセージを追加します。後続の操作が成功した場合は、メッセージを削除します。失敗した場合は、確認メッセージを送信します。 次に、非同期ロジックを使用してメッセージをリッスンし、対応する処理を実行します。これは基本的に、ローカル メッセージ テーブルの処理ロジックと同じです。ただし、メッセージ サービスへのメッセージの追加はローカル操作と同じトランザクションに含めることができないため、メッセージは正常に追加されたものの後で失敗する状況が発生する可能性があります。この場合、メッセージは役に立ちません。 以下にシナリオ例を示します。
この無意味なメッセージでは、メッセージ サービスがメッセージが正常に実行されたかどうかを確認する必要があります。そうでない場合は削除されます。はいの場合は、後続のロジックが引き続き実行されます。ローカル トランザクション テーブルの try および confirm と比較すると、メッセージ サービスには、先頭に追加の状態 prepare があります。 MQ トランザクションRocketMQ などの一部の MQ 実装ではトランザクションがサポートされています。 MQ トランザクションは、まったく同じロジックを持つ、独立したメッセージ サービスの特定の実装として考えることができます。 すべての操作の前に、メッセージが MQ に配信されます。後続の操作が成功した場合はメッセージの送信を確定し、失敗した場合はメッセージを削除してキャンセルします。 MQ トランザクションは準備状態でも存在し、ビジネスが成功したかどうかを確認するには MQ コンシューマー処理ロジックが必要です。 要約する分散システムの実践の観点から、データの一貫性を確保するためには、追加のメカニズム処理を導入する必要があります。 TCC の利点は、ビジネス サービス層で動作し、特定のデータベースに依存せず、特定のフレームワークと結合されておらず、リソース ロックの粒度が柔軟であるため、マイクロサービス シナリオに非常に適していることです。欠点は、各サービスが 3 つの API を実装する必要があり、これによりビジネスへの重大な侵入と変更が発生し、さまざまな障害例外の処理が必要になることです。開発者がさまざまな状況に完全に対処するのは困難です。 Alibaba の Fescar のような成熟したフレームワークを見つけることで、コストを大幅に削減できます。 ローカル メッセージ テーブルの利点は、シンプルで、他のサービスの変換に依存せず、サービス呼び出しや MQ と組み合わせて使用でき、ほとんどのビジネス シナリオでより実用的であることです。欠点は、ローカル データベースにビジネス テーブルと結合された追加のメッセージ テーブルがあることです。この記事のローカル メッセージ テーブル メソッドの例は、著者が作成したライブラリから取得したものです。興味のある学生はhttps://github.com/mushroomsir/tccを参照してください。 MQ トランザクションと独立したメッセージ サービスの利点は、トランザクションの問題を解決するために共通のサービスが抽出され、各サービスがメッセージ テーブルを持ち、サービスと結合されてサービス自体の処理の複雑さが増す状況を回避できることです。欠点は、トランザクションをサポートする MQ が非常に少ないことです。また、各操作の前に API を呼び出してメッセージを追加すると、呼び出し全体の待ち時間が増加します。これは、通常の応答を伴うほとんどのビジネス シナリオでは不要なオーバーヘッドになります。 |
<<: クラウドコンピューティングは新エネルギー車よりも排出量を削減する
>>: アリババは、NvidiaやGoogleと比較してコンピューティング電力消費を80%削減する1兆パラメータのAIモデルM6をリリースしました。
過ぎ去ったばかりの2021年は、テクノロジーがこれまで以上に重要であることを間違いなく証明しました。...
[51CTO.com クイック翻訳]急速に台頭している 2 つのテクノロジー、コードとしてのモニタリ...
Baidu の最適化を行っている友人にとって、Baidu Index は常に無視できないデータ情報で...
マイクロサービス アーキテクチャを実装する企業が増えるにつれて、コミュニティにおけるサービス メッシ...
[[378468]] 1. いかだの概要Raft アルゴリズムは、分散システム開発に適したコンセンサ...
ゴン・ハイヤン新浪テクノロジー 神雲芳創業者のGong Haiyan氏の辞任と分散化により、Jiay...
Godaddy では、Godaddy のエコノミー モデル仮想ホストを 1 年間 + 無料ドメイン名...
先ほど、Dapr でサービス呼び出しを行う方法と、最も単純な状態管理について学習しました。このセクシ...
最近では、フォーラムプロモーション、ブログプロモーション、質疑応答プロモーション、電子メールプロモー...
WeChat マーケティングに関しては、誰もがよく知っていると思います。ただし、WeChat 上のユ...
ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスSEO担当者として、ウェ...
最近、一部のネットユーザーから、bluehostが中国語のウェブサイトを立ち上げたという報告がありま...
バージョン 1.20 以降、Kubernetes はコンテナ ランタイムとして Docker を使用...
desivps は最近、中国のお客様向けに特別プロモーション VPS を開始しました (年間 6 回...
shockhosting.net の主な事業は仮想ホスティングと VPS です。すべての VPS サ...