注意してください! Kafka と RabbitMQ を無差別に使用しないでください…

注意してください! Kafka と RabbitMQ を無差別に使用しないでください…

経験豊富なマイクロサービス システム アーキテクトとして、RabbitMQ と Kafka のどちらを選ぶべきかとよく尋ねられます。

[[320896]]

画像はPexelsより

何らかの理由で、多くの開発者はこれら 2 つのテクノロジを同等のものとして扱います。実際、いくつかのケースのシナリオでは、RabbitMQ と Kafka のどちらを選択しても違いはありませんが、基盤となる実装の点では、これら 2 つのテクノロジの間には多くの違いがあります。

シナリオによって必要なソリューションは異なり、間違ったソリューションを選択すると、ソフトウェアの設計、開発、保守の能力に重大な影響を与える可能性があります。

最初の記事では、RabbitMQ と Apache Kafka の内部実装に関連する概念を紹介しました。この記事では、これら 2 つのテクノロジの違いを 2 つの側面から検討します。1 つは 2 つのテクノロジ間の重要な違いであり、もう 1 つはソフトウェア アーキテクトと開発者が注意を払う必要がある違いです。

まず、これら 2 つのテクノロジーを使用して実装しようとしているアーキテクチャ パターンについて説明し、それぞれをいつ使用するか評価しましょう。

注 1: RabbitMQ と Kafka の内部構造に詳しくない場合は、前回の最初の記事「RabbitMQ と Kafka のどちらを選ぶべきか」を読むことを強くお勧めします。

よくわからない場合は、タイトルとチャートをざっと見て、少なくとも大まかな違いを把握してください。

注 2: 前回の記事が公開された後、何人かの読者から Apache Pulsar についてどう思うかと尋ねられました。 Pulsar は、RabbitMQ と Kafka の両方の利点のいくつかを提供することを目的とした別のタイプのメッセージング システムです。

現代的なメッセージング システムとしては有望に思えます。しかし、他のプラットフォーム システムと同様に、長所と短所があります。

この記事では主に RabbitMQ と Kafka を比較します。後で Apache Pulsar との比較をしてみたいと思います。

RabbitMQとKafkaの大きな違い

RabbitMQ はメッセージブローカーですが、Apache Kafka は分散ストリーミングシステムです。セマンティクスからは違いがわかるようですが、それらの内部特性のいくつかは、さまざまなユースケースをうまく設計できるかどうかに影響します。

たとえば、Kafka はストリーミング データに最適ですが、RabbitMQ ではストリーム内のメッセージの順序を維持するのが困難です。

一方、RabbitMQ には再試行ロジックとデッドレター交換が組み込まれていますが、Kafka では実装ロジックがユーザーに任されています。

このセクションでは、さまざまなシステム間の主な違いに焦点を当てます。

メッセージの順序

RabbitMQ は、キューまたは交換に送信されるメッセージの順序を保証しません。コンシューマーがプロデューサーからのメッセージを順番に処理するのは論理的に思えますが、これは非常に誤解を招きます。

RabbitMQ のドキュメントには、メッセージ順序の保証について次のように記載されています。

「チャネルに公開され、エクスチェンジ、キュー、および出力チャネルを使用して配信されたメッセージは、最終的には送信された順序で受信されます。」

——RabbitMQ ブローカーセマンティクス

言い換えれば、私たちが単一の消費者である限り、受け取るメッセージは順序どおりです。ただし、複数のコンシューマーが同じキューからメッセージを読み取ると、メッセージが処理される順序は保証されません。

コンシューマーはメッセージを読み取った後にキューに戻す(または再送信する)ことがあるため(処理が失敗した場合など)、メッセージの順序は保証されません。

メッセージがキューに戻されると、別のコンシューマーは、キューに戻されたメッセージの後のメッセージをすでに処理していたとしても、そのメッセージの処理を続行できます。

したがって、コンシューマー グループは、次の表に示すように、メッセージを順序どおりに処理しません。

RabbitMQ を使用したメッセージ順序の消失の例

もちろん、コンシューマーの同時実行数を 1 に制限することで、RabbitMQ でのメッセージの順序を確保できます。

より正確に言うと、並列メッセージ処理によって順序が乱れる問題が発生するため、単一のコンシューマー内のスレッド数を 1 に制限します。

ただし、システム規模が大きくなるにつれて、シングルスレッドのコンシューマー モデルはメッセージ処理機能に重大な影響を与えます。したがって、このオプションを軽々しく選択すべきではありません。

一方、Kafka では、メッセージ処理において信頼性の高い順序保証が提供されます。 Kafka は、同じトピック パーティションに送信されたすべてのメッセージが順番に処理されることを保証します。

最初の記事で説明したように、Kafka はデフォルトでラウンドロビン パーティショナーを使用して、対応するパーティションにメッセージを配置します。

ただし、プロデューサーは各メッセージにパーティション キーを設定して、データの論理フローを作成できます (同じデバイスからのメッセージや、同じテナントに属するメッセージなど)。

同じストリームからのすべてのメッセージは同じパーティションに配置されるため、コンシューマー グループが順番に処理できます。

ただし、同じコンシューマー グループ内では、各パーティションが 1 つのコンシューマーの 1 つのスレッドによって処理されることにも注意する必要があります。その結果、単一のパーティションの処理能力を拡張できなくなります。

ただし、Kafka では、トピック内のパーティションの数をスケーリングして、各パーティションがより少ないメッセージを処理するようにし、追加のパーティションを処理するためにコンシューマーを追加することができます。

勝者: メッセージの順序どおりの処理を保証する Kafka が明らかに勝者です。 RabbitMQ はこの分野では比較的弱いです。

メッセージルーティング

RabbitMQ は、定義されたサブスクライバー ルーティング ルールに基づいて、メッセージ交換でサブスクライバーにメッセージをルーティングできます。トピック交換は、routing_key と呼ばれる特別なヘッダーを介してメッセージをルーティングできます。

あるいは、ヘッダー交換では、任意のメッセージ ヘッダーに基づいてメッセージをルーティングできます。どちらの交換でも、消費者は関心のあるメッセージ タイプを効果的に設定できるため、ソリューション アーキテクトに大きな柔軟性が提供されます。

一方、Kafka では、コンシューマーがトピック内のメッセージを処理する前にフィルタリングすることはできません。サブスクライブされたコンシューマーは、特に指定がない限り、パーティション内のすべてのメッセージを受信します。

開発者は、トピックからメッセージを読み取り、フィルター処理し、フィルター処理されたメッセージをコンシューマーがサブスクライブできる別のトピックにプッシュする Kafka ストリーミング ジョブを使用できます。ただし、これにはより多くの作業とメンテナンスが必要になり、可動部品も増えます。

勝者: RabbitMQ は、メッセージのルーティングとフィルタリングをより適切にサポートします。

メッセージのタイミング

RabbitMQ は、キューに送信されるメッセージのタイミングを設定するためのいくつかの機能を提供します。

①メッセージ生存時間(TTL)

RabbitMQ に送信されるすべてのメッセージには、TTL プロパティを関連付けることができます。パブリッシャーは、TTL を直接設定することも、キューのポリシーに従って設定することもできます。

システムは、設定された TTL に応じてメッセージの有効期間を制限できます。コンシューマーが予想時間内にメッセージを処理しない場合、メッセージはキューから自動的に削除されます (後続のすべてのメッセージと同様に、デッドレター交換に移動されます)。

TTL は、時間に敏感なコマンドに特に役立ちます。これらのコマンドは、一定期間内に処理されないと意味がなくなるためです。

②遅延・予定ニュース

RabbitMQ は、プラグインを介して遅延メッセージまたはスケジュールされたメッセージをサポートできます。メッセージ交換でこのプラグインを有効にすると、プロデューサーは RabbitMQ にメッセージを送信でき、プロデューサーは RabbitMQ がメッセージをコンシューマー キューにルーティングするのにかかる時間を遅らせることができます。

この機能により、開発者は将来のコマンド、つまりそれ以前に処理されるべきではないコマンドをスケジュールできます。

たとえば、プロデューサーがスロットリング ルールに遭遇すると、それらの特定のコマンドの実行が後で延期されることがあります。

Kafka はこれらの機能を提供しません。メッセージが到着するとすぐにパーティションに書き込まれるため、コンシューマーはメッセージをすぐに処理できます。

Kafka はメッセージに対して TTL メカニズムを提供しませんが、アプリケーション層で実装できます。

ただし、覚えておかなければならないのは、Kafka パーティションは追加モードのトランザクション ログであるということです。したがって、メッセージのタイミング (またはパーティション内の位置) を処理することはできません。

勝者: この実装は本質的に Kafka に限定されているため、RabbitMQ が間違いなく勝者です。

メッセージの保持

コンシューマーがメッセージを正常に消費すると、RabbitMQ は対応するメッセージをストレージから削除します。この動作は変更できません。これは、ほぼすべてのメッセージ ブローカー設計に不可欠な部分です。

逆に、Kafka はトピックごとにタイムアウトを設定し、タイムアウトに達していないすべてのメッセージは保持されます。

メッセージの保持に関しては、Kafka はそれをメッセージ ログとしてのみ扱い、コンシューマーの消費ステータスは考慮しません。

コンシューマーは各メッセージを無制限に使用でき、パーティション オフセットを操作してこれらのメッセージを時間的に「前後に」処理できます。

Kafka はパーティション内のメッセージの保持時間を定期的にチェックします。設定された保存期間を超えると、メッセージは削除されます。

Kafka のパフォーマンスはストレージ サイズに依存しません。したがって、理論的には、そこにメッセージを保存してもパフォーマンスにほとんど影響はありません (ノードにそれらのパーティションを保持するのに十分なスペースがある限り)。

勝者: Kafka はメッセージを保存するように設計されていますが、RabbitMQ はそうではありません。したがって、ここでは比較の余地はなく、カフカが勝者です。

フォールトトレランス

メッセージ、キュー、イベントを扱う場合、開発者はメッセージ処理が常に成功すると想定することがよくあります。結局のところ、プロデューサーが各メッセージをキューまたはトピックに配置すると、コンシューマーがメッセージの処理に失敗しても、成功するまで再試行するだけです。

このアプローチは表面的には正しいように思えますが、よく考える必要があります。まず、シナリオによってはメッセージの処理が失敗する可能性があることを認識する必要があります。

したがって、ソリューションの一部に人間の介入が必要な場合でも、それらの状況を適切に処理する必要があります。

メッセージ処理では、次の 2 つの障害が発生する可能性があります。

  • 一時的な障害: ネットワーク接続、CPU 負荷、サービスのクラッシュなどの一時的な問題により障害が発生します。何度も試行することで、この失敗を軽減することができます。
  • 永続的な障害: 障害は、追加の再試行では解決できない永続的な問題によって発生します。一般的な原因としては、ソフトウェアのバグや無効なメッセージ形式(破損した(有害な)メッセージなど)が挙げられます。

設計者や開発者として、私たちは自分自身に問いかける必要があります。「メッセージ処理の失敗を何回再試行すればよいのか。再試行の間隔はどのくらいにすればよいのか。一時的な障害と永続的な障害をどのように区別すればよいのか。」

最も重要なのは、「すべての再試行が失敗した場合、または永続的な障害が発生した場合、どうすればよいか」ということです。

もちろん、ビジネス分野が異なれば答えも異なりますが、メッセージング システムは通常、独自のソリューションを実装するためのツールを提供します。

RabbitMQ は、メッセージ処理の失敗を処理するために、配信の再試行やデッドレター交換 (DLX) などの機能を提供します。

DLX の主なアイデアは、適切な構成情報に従ってルーティング障害メッセージを DLX に自動的に送信し、例外再試行、再試行回数、および「人間の介入」キューへの送信などのスイッチ上のルールに従ってさらに処理することです。

RabbitMQで再試行を処理するための可能なパターンについての追加の洞察を提供するこの記事[1]を参照してください。

RabbitMQ で覚えておくべき最も重要なことは、1 つのコンシューマーがメッセージを処理または再試行している間 (キューに返す前であっても)、他のコンシューマーがこのメッセージに続く他のメッセージを同時に処理できるということです。

コンシューマーがメッセージの処理を再試行する場合、メッセージ処理ロジック全体はブロックされません。

したがって、コンシューマーは、システム全体の動作に影響を与えることなく、どれだけ時間がかかってもメッセージの処理を同期的に再試行できます。

コンシューマー1はメッセージ1の処理を再試行し続け、他のコンシューマーは他のメッセージの処理を続行できる。

RabbitMQ とは異なり、Kafka はそのようなメカニズムをすぐに使用できるようには提供していません。 Kafka では、アプリケーション層でメッセージ再試行メカニズムを提供して実装する必要があります。

さらに、コンシューマーが特定のメッセージを同期的に処理している場合、同じパーティション上の他のメッセージは処理できないことに注意する必要があります。

コンシューマーはメッセージの順序を変更できないため、特定のメッセージを拒否して再試行し、その後に続くメッセージを送信することはできません。パーティションは単なる追加モードのログであることを覚えておいてください。

アプリケーション層のソリューションとしては、失敗したメッセージを「再試行トピック」に送信し、そのトピックからの再試行を処理することが考えられます。ただし、その場合、メッセージの順序は失われます。

Uber のエンジニアが実装したこの例は、Uber.com でご覧いただけます。メッセージ処理の遅延が問題にならない場合は、エラーを適切に監視する Kafka ソリューションで十分な場合があります。

コンシューマーがメッセージの再試行をブロックされている場合、下位パーティションのメッセージは処理されません。

勝者: この問題を解決するためのすぐに使用できるメカニズムを提供する RabbitMQ が勝者です。

ストレッチ

RabbitMQ と Kafka のパフォーマンスをチェックするベンチマークがいくつかあります。

一般的なベンチマークは特定の状況に限定される場合がありますが、一般的に Kafka は RabbitMQ よりも優れたパフォーマンスを発揮すると考えられています。

Kafka はパフォーマンスを向上させるためにシーケンシャル ディスク I/O を使用します。 Kafka のパーティショニング アーキテクチャから判断すると、水平拡張では RabbitMQ よりも優れています。もちろん、RabbitMQ は垂直拡張においてより多くの利点があります。

Kafka の大規模な展開では、通常、1 秒あたり数十万件、さらには数百万件のメッセージを処理できます。

過去に、Pivo​​talは1秒あたり100万件のメッセージを処理するKafkaクラスターを文書化しました[2]。ただし、これは 30 ノードのクラスターで実行され、メッセージの負荷は複数のキューと交換にわたって最適に分散されました。

一般的な RabbitMQ の展開は 3 ~ 7 個のノードのクラスターで構成され、これらのクラスターでは負荷を異なるキューに分散する必要はありません。これらの典型的なクラスターは、通常、1 秒あたり数万件のメッセージを処理することが期待されます。

勝者: どちらのメッセージング プラットフォームも大きな負荷を処理できますが、Kafka の方がスケーリングが優れており、RabbitMQ よりも高いスループットを実現できるため、このラウンドでは Kafka が勝利します。

ただし、ほとんどのシステムはまだこれらの制限に達していないことに注意してください。したがって、何百万ものユーザーを抱える次世代の非常に人気のあるソフトウェア システムを構築しているのでない限り、スケーラビリティについてあまり心配する必要はありません。結局のところ、どちらのメッセージング プラットフォームも問題なく動作します。

消費者の複雑さ

RabbitMQ はスマートブローカーとダムコンシューマーモデルを使用します。コンシューマーはコンシューマー キューに登録し、RabbitMQ は受信メッセージをコンシューマーにプッシュします。 RabbitMQ にはプル API もあります。ただし、ほとんど使用されません。

RabbitMQ は、メッセージの配布とキューからのメッセージの削除 (および DLX への転送) を管理します。消費者はこれを考慮する必要はありません。

RabbitMQ アーキテクチャの設計によれば、負荷が増加すると、システムに変更を加えなくても、キュー上のコンシューマー グループを 1 つのコンシューマーから複数のコンシューマーに効果的に拡張できます。

RabbitMQ 効率的なスケーリング

対照的に、Kafka はダムブローカーとスマートコンシューマーモデルを使用します。コンシューマー グループ内のコンシューマーは、それらの間でトピック パーティションのリースを調整する必要があります (特定のパーティションがコンシューマー グループ内の 1 人のコンシューマーによってのみリッスンされるように)。

コンシューマーはパーティション オフセット インデックスを管理および保存する必要もあります。幸いなことに、Kafka SDK ではすでにカプセル化されているため、自分で管理する必要はありません。

さらに、負荷が低い場合、単一のコンシューマーが複数のパーティションを並行して処理および管理する必要があり、コンシューマー側でより多くのリソースが消費されます。

もちろん、負荷が増加するにつれて、コンシューマーの数がトピック内のパーティションの数と等しくなるようにコンシューマー グループをスケーリングする必要があります。これには、追加のパーティションを追加するように Kafka を構成する必要があります。

ただし、負荷が再び減少すると、以前に追加したパーティションを削除できなくなり、コンシューマーにさらに作業を追加する必要があります。

それにもかかわらず、上で述べたように、Kafka SDK はすでにこの追加作業を実行しています。

Kafka パーティションは削除できず、スケールダウン後にコンシューマーはより多くの作業を行うことになります。

勝者: RabbitMQ は、設計上、愚かな消費者向けに構築されています。つまり、このラウンドでは RabbitMQ が勝利します。

どうやって選ぶ?

今、私たちは「RabbitMQ をいつ使用し、Kafka をいつ使用するのか」という重要な質問に直面しています。上記の違いをまとめると、次のような結論を導き出すのは難しくありません。

以下の場合には RabbitMQ が推奨されます。

  • 高度で柔軟なルーティングルール
  • メッセージタイミング制御(メッセージの有効期限またはメッセージの遅延の制御)
  • コンシューマーがメッセージ(一時的または永続的)の処理に失敗する可能性が高いシナリオにおける高度なフォールト トレランス
  • よりシンプルな消費者実装

Kafka を優先する:

  • 厳密なメッセージ順序
  • 過去のメッセージを再生する可能性を含め、メッセージの保存期間を延長する
  • 従来のソリューションでは満たせない高い拡張性

ほとんどの場合、これら 2 つのメッセージング プラットフォームで要件を満たすことができます。しかし、最も適切なツールを選択するのは私たち建築家次第です。

決定を下す際には、上で強調した機能上の違いと非機能上の制限を考慮する必要があります。

これらの制限は次のとおりです。

  • 現在の開発者のこれら2つのメッセージングプラットフォームに対する理解
  • マネージドクラウドソリューションの可用性(該当する場合)
  • 各ソリューションの運用コスト
  • ターゲットスタックのSDKの可用性

複雑なソフトウェア システムを開発する場合、必要なすべてのメッセージング ユース ケースを実装するために同じメッセージング プラットフォームを使用したくなることがあります。

しかし、私の経験では、両方のメッセージング プラットフォームを併用すると、通常はより多くのメリットが得られます。

たとえば、イベント駆動型アーキテクチャ システムでは、RabbitMQ を使用してサービス間でコマンドを送信し、Kafka を使用してビジネス イベント通知を実装できます。

その理由は、イベント通知はイベント トレース、バッチ操作 (ETL スタイル)、または監査の目的でよく使用されるため、Kafka のメッセージ保持機能は非常に価値があるからです。

対照的に、コマンドは通常、コンシューマー側で追加の処理を必要とし、その処理は失敗する可能性があるため、高度なフォールト トレランス機能が必要です。

ここで、RabbitMQ には多くの優れた機能があります。これについては将来的に詳細な記事を書くかもしれませんが、覚えておいていただきたいのは、適合性は特定のニーズによって異なるため、結果は異なる可能性があるということです。

要約する

これら 2 つの記事を書いた理由は、多くの開発者が RabbitMQ と Kafka を同等のものとして扱っていることに気づいたからです。

これら 2 つの記事を参考にして、2 つの技術的実装とそれらの技術的な違いについて深く理解していただければ幸いです。

これにより、2 つのプラットフォームは、その違いを通じてユースケースに適したサービスを提供するようになります。どちらのメッセージング プラットフォームも優れており、さまざまなユース ケースに非常によく対応します。

しかし、ソリューション アーキテクトとして、各ユース ケースの要件を理解し、最適化し、最も適切なソリューションを選択するのは私たちの責任です。

関連リンク:

  • https://engineering.nanit.com/rabbitmq-retries-the-full-story-ca4cc6c5b493
  • https://content.pivotal.io/blog/rabbitmq-hits-one-million-messages-per-second-on-google-compute-engine

<<:  クラウドコンピューティング半月刊第76号 - マイクロソフトが5Gおよびエッジコンピューティング企業Affirmed Networksを買収

>>:  マイクロソフト、グーグル、アマゾンのクラウド競争が新たな局面を開く:コードを書かずに短時間でアプリケーションを構築

推薦する

マルチクラウドの台頭とエンタープライズハイブリッドITの発展

クラウド コンピューティングにおける 10 年間の開発と革新を経て、企業は現在、すべてをパブリック ...

Douban FM: 「気取った」ユーザーに課金することで無料ユーザーから広告料を稼ぐ

Douban FMの有料版が最近リリースされ、月額10元で、ユーザー課金モデルの模索が正式に始まった...

タオバオのオンライン広告費が急増:売り手は「タオバオを離れる」ことを望んでいる

李娜[暁丁は、巨華軒のイベントの売上高は15万元、広告費は5万元で、最終的に商人は在庫しか稼げなかっ...

リンギング:718 Apple製品JDスーパーブランドデーはインターネットのトレンドをどのように反映していますか?

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますフランスチ...

共同購入サイトの半数が破産の危機に直面しており、多くが変革するだろう

共同購入ウェブサイトは全面的な変革を遂げ、お金を無駄にする時代は終わりました。東莞タイムネットワーク...

元社員が語る:Weiboマーケティングの8つのヒント

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービス多くのブランド広告主がW...

ソフト記事プロモーション市場は混在しています。ウェブマスターはどのようにして正規のソフト記事マーケティング会社を選択すればよいのでしょうか?

インターネットは日々変化しており、オンラインプロモーションも日々変化しています。従来の方法を適切に使...

百度は検索の未来を見据える

私たち中国人の目には、百度は超強力なツールです。百度のない生活が停電や水不足と同じくらい耐え難いもの...

おすすめ: Bluehost - 年間 12 ドル - 感謝祭/ブラックフライデー/サイバーマンデー

Bluehost は現在、米国最大の仮想ホスティング会社です。10 年以上の歴史があり、EIG コン...

SEO のやり方は? 高品質なソフト記事の重みはどれくらいですか?

多くのウェブサイトビルダーは、SEO という略語に精通しています。なぜなら、ウェブサイトビルダーはこ...

ショッピングガイド電子商取引はタオバオ中毒から抜け出す:価値を最大化する課題

「これは見逃せないトレンドだ」。モグジエのシリーズC資金調達に関わった関係者は、資金調達額の具体的な...

2022年までに産業企業の90%がエッジコンピューティングを使用する

Frost & Sullivan の最近のレポートによると、エッジ コンピューティングは、レ...

ソフト製品の有効性をデジタルで評価する方法

ソフトな物品が効果的であることはわかっていますが、この効果の概念は非常に曖昧です。 SEO の効果を...

地域BBSがソーシャルネットワークのトラフィックコンバージョン率を突破

中関村のようなハイテクの敷居を持たず、強力なバックエンドに依存せず、宣伝や展開に多額の資金を必要とせ...

外部リンク数の減少の原因を突き止め、外部リンク最適化のボトルネックを打破する

Baidu アルゴリズムの調整により、SEO 最適化を行った多くのウェブサイトでは、外部リンクの数が...