[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?
#############################################I.はじめに##
# 私たちの友人は、RabbitMQ、RocketMQ、Kafka などのメッセージ ミドルウェア MQ について十分に聞いているはずです。ミドルウェアを導入するメリットは、高い同時実行性、ピーキング、ビジネスの分断に対抗する役割を果たす可能性があります。
上に示すように:
(1) オーダー サービスは MQ ミドルウェアにメッセージを配信します (2) ロジスティクス サービスは消費される MQ ミドルウェア メッセージを監視します
![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/f852e96ec4ede8017b2939233ca31b59-2.jpg?x-oss-process=image/resize,p_40)
シナリオについて話しましょう。MQ サーバーが突然ダウンしたらどうなりますか?注文サービスから送信されたメッセージはすべて消えてしまったのでしょうか?はい、通常、MQ ミドルウェアはシステムのスループットを向上させるためにメッセージをメモリに保存します。他の処理が行われない場合、MQ サーバーがダウンするとすべてのメッセージが失われます。これはビジネスでは許可されていないため、大きな影響を及ぼします。
経験豊富な友人は、メッセージを永続化して RabbitMQ でメッセージを送信する方法があると言うでしょう。設定可能な永続パラメータ。true に設定すると永続的になります。
![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/905609ce0cc6322832dab4f86e7a7ed2-4.jpg?x-oss-process=image/resize,p_40)
この場合、MQ サーバーがダウンしても、メッセージは再起動後にディスク ファイルに保存されるため、メッセージは失われません。はい、これにより、メッセージが一定の確率で失われないことが保証されます。
しかし、メッセージが MQ メモリに保存されたばかりで、ディスク ファイルに更新される前に突然クラッシュするというシナリオも考えられます。 (なんと、これは短期間で起こります。確率が低すぎます。) このシナリオは、継続的な大規模メッセージ配信のプロセスでは非常に一般的です。 ######私たちは何をすべきか?ディスクに確実に保存するにはどうすればよいでしょうか?
確認メカニズムの原理: 上記の問題は、永続化が成功したかどうかを誰も教えてくれないという事実から発生します。幸いなことに、多くの MQ にはコールバック通知機能があり、RabbitMQ には永続化が成功したかどうかを通知する確認メカニズムがあります。
![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/21e84d146b7e6f7efb17ced97484e602-5.jpg?x-oss-process=image/resize,p_40)
上記の疑似コードには、次の 2 つの方法があります。メッセージを処理します。これは、ack コールバックと nack コールバックです。(2) メッセージの受信が失敗した場合、MQ はプロデューサーに nack メッセージを返します。
![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/21e84d146b7e6f7efb17ced97484e602-6.jpg?x-oss-process=image/resize,p_40)
これにより、メッセージが 100% 失われないことが保証されますか?
確認メカニズムを見てみましょう。プロデューサがメッセージを送信するたびに、MQ をディスクに永続化し、ack または nack コールバックを開始する必要があると想像してください。この場合、メッセージを毎回ディスクに保存する必要があるため、MQ のスループットは非常に低くなります。ディスクへの書き込みが非常に遅いです。これは同時実行性が高いシナリオでは受け入れられず、スループットが低すぎます。
MQ 永続ディスクの実際の実装は、非同期呼び出しによって処理され、特定のメカニズムがあり、たとえば、数千のメッセージがある場合、一度にディスクにフラッシュされます。メッセージが届くたびにディスクをフラッシュするのではなく。
つまり、comfirm メカニズムは実際には、システムの高スループットを確保するための非同期リスニング メカニズムです。これは、メッセージが失われないことが 100% 保証されていないことを意味します。確認メカニズムが追加されると、メッセージは失われません。メモリがディスクにフラッシュされる前に MQ がクラッシュし、それでも処理できませんでした。
ここまで言いましたが、まだ保証はできません。どうすればよいでしょうか? ? ?
5. 事前にメッセージを永続化する スケジュールされたタスク
実は、本質的な理由は、永続化されているかどうかを判断できないことです。では、メッセージを自分で永続化できるでしょうか?答えは「はい」です。私たちの計画はさらに進化します。
![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/21e84d146b7e6f7efb17ced97484e602-7.jpg?x-oss-process=image/resize,p_40)
上の図のプロセス:
(1) 注文サービスプロデューサーがメッセージを配信する前に、メッセージを Redis または DB に永続化する必要があります。パフォーマンスの高い Redis をお勧めします。メッセージのステータスは送信中です。
(2) 確認メカニズム監視メッセージは正常に送信されましたか? ACK が成功した場合は、Redis でこのメッセージを削除します。
(3) nack が失敗した場合、メッセージを再送信するかどうかは、業務に応じて選択できます。ビジネス上の決定に応じて、このメッセージを削除することもできます。
(4) 一定期間後にメッセージをプルするスケジュールされたタスクがここに追加されます。メッセージ ステータスはまだ送信中です。このステータスは、注文サービスが確認応答メッセージを受信していないことを示します。
(5) スケジュールされたタスクは、補償メッセージを配信します。このとき、MQ コールバック ACK が正常に受信されると、Redis 内でメッセージが削除されます。
このようなメカニズムは実際には補償メカニズムです。MQ が実際にそれを受信するかどうかは関係ありません。Redis 内のメッセージのステータスが [送信中] である限り、メッセージが送信されていることを意味します。正しく受信できませんでした。次に、スケジュールされたタスクを開始して、補償の配信を監視および開始します。
もちろん、スケジュールされたタスクに補正番号を追加することもできますが、3 回を超えても ack メッセージが受信されない場合は、メッセージのステータスを直接 [失敗] に設定し、手動でチェックしてください。なぜですか?
この場合、ソリューションは比較的完璧で、メッセージの 100% が失われないことが保証されています (もちろん、ディスク障害は含まれていないため、マスター/スレーブ ソリューションを使用できます)。
ただし、このソリューションでは、同じメッセージを複数回送信することができます。MQ はすでにメッセージを受信している可能性が非常に高いですが、ack メッセージのコールバック中にネットワーク障害が発生し、プロデューサーはそれを受け取りませんでした。
次に、消費時に冪等性を確保することを消費者に要求する必要があります。
6. べき等性の意味
まず、べき等性とは何かを理解しましょう。分散アプリケーションでは、冪等性、つまり、同じ条件でビジネスを実行すれば、何度実行しても結果は同じであることが非常に重要です。
6.1. 冪等のようなシナリオが存在するのはなぜですか?
なぜ冪等のようなシナリオがあるのでしょうか?大規模なシステムでは、すべてが分散して展開されるため、たとえば、受注業務と在庫業務が独立して別のサービスとして展開される場合があります。ユーザーが注文すると、注文サービスと在庫サービスが呼び出されます。
![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/7f9e506a95a9be69dfb9b373d1a8cf52-8.jpg?x-oss-process=image/resize,p_40)
分散配置により、インベントリ サービスを呼び出すときに、ネットワークやその他の理由で注文サービスの呼び出しが失敗する可能性が非常に高くなりますが、実際にはインベントリ サービスは処理されており、次の場合にのみ表示されます。処理結果は注文サービスに返されます。例外。この時点で、システムは通常、補償計画を作成します。つまり、注文サービスが在庫サービスを呼び出し、在庫が 1 つ減ります。
![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/7f9e506a95a9be69dfb9b373d1a8cf52-9.png?x-oss-process=image/resize,p_40)
#問題があります。実際、最後の呼び出しは 1 減りましたが、注文サービスは処理結果を受け取っていません。ここで再び呼び出され、1 減らす必要があります。これはビジネスに合致しておらず、追加の控除です。
冪等性の概念は、同じ条件でインベントリ サービスを何度呼び出しても、処理結果は同じになるということです。この方法によってのみ、補償計画の実現可能性が保証されます。
#6.2. オプティミスティック ロック スキーム
次のようなデータベースのオプティミスティック ロック メカニズムから学習します。 #バージョンに基づいて、つまり、インベントリを操作する前に現在の製品のバージョン番号を取得し、操作時にこのバージョン番号を持参します。整理しましょう。初めて在庫を操作したときはバージョン 1 が取得され、在庫サービスを呼び出したときにバージョンは 2 になりました。しかし、注文サービスに戻るときに問題が発生しました。注文サービスは別のサービスを開始しました。在庫サービスへの呼び出し オーダーサービスがバージョン1のままで渡された場合、上記のSQL文を再度実行してもバージョンが2に変わっているため実行されず、where条件が成立しません。これにより、何度呼び出されても、処理されるのは 1 回だけになります。![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/7f9e506a95a9be69dfb9b373d1a8cf52-10.png?x-oss-process=image/resize,p_40)
原則は、データベースの主キーを使用して重複を削除し、その後に主キー ID を挿入することです。ビジネスは完了しました
![[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?](https://img.php.cn/upload/article/001/273/690/e808668e894a210e81b1ff1c1ec367b8-11.jpg?x-oss-process=image/resize,p_40)
フィンガープリント コードは、通常の操作ごとにコードを区別するためのもので、操作ごとに生成され、タイムスタンプのビジネス番号が使用できます。
上記の SQL ステートメント:
戻り値が 0 の場合、操作が実行されていないことを意味します。ビジネス オペレーションの後で実行できます。 t_check (一意の ID フィンガープリント コード) に挿入します。
Return 0 より大きい場合、オペレーションが実行されたことを意味します。
利点: シンプルな実装
欠点: 同時実行性が高い場合のデータベースのボトルネック
解決策: データベースとテーブルを分割するアルゴリズム ルーティングの ID
6.4、Redis アトミック操作
Redis のアトミック操作を使用して、操作の完了をマークします。このパフォーマンスの方が優れています。しかし、いくつかの問題もあるでしょう。
最初: ビジネス結果をデータベースに保存する必要がありますか?その場合、解決すべき重要な問題は、データベースと Redis 操作でアトミック性を実現する方法です?
これはインベントリが 1 減少することを意味しますが、redis 操作がマークを完了するときに失敗した場合はどうすればよいでしょうか?つまり、データベースの削除と redis が同時に成功するか失敗するかを確認する必要があります。
2 番目: データベースが削除されない場合、両方ともキャッシュに保存されます。同期戦略?
これは、インベントリが 1 減り、インベントリは削除されないことを意味します。Redis 操作を直接実行してマーキングを完了し、別の同期サービスを使用してインベントリを削除します。これは、システムと同期戦略の複雑さが増します。セットアップ方法
以上が[インタビュー] メッセージを 100% 確実に配信するにはどうすればよいですか?メッセージの冪等性を確保するにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

ドリームウィーバー CS6
ビジュアル Web 開発ツール

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

ホットトピック









