KafkaとNATS:メッセージ処理の比較

分散アーキテクチャでは、システム間の通信が全体のインフラストラクチャの基盤を形成します。インフラストラクチャのパフォーマンス、スケーラビリティ、信頼性は、イベント/メッセージ/データがどのように交換され、持続されるかに大きく依存します。

KafkaとNATSは、ストリーミングとメッセージングを扱うための二つの人気のあるツールです。これらは異なるアーキテクチャと異なるパフォーマンス特性を持っています。特定のユースケースに適しています。この記事では、NATSの特徴とKafkaを比較し、私が仕事で取り上げたユースケースについて説明します。

1. アーキテクチャと複雑性

NATS

NATSインフラストラクチャは二つの主要なコンポーネントを持ちます:

コアNATS

コアNATSは基本的なメッセージングフレームワークです。これにより、Publish-Subscribe(メッセージを複数の購読者にブロードキャスト可能)、Request-Reply(同期通信を可能にする)、Queue Groups(グループ内の複数の購読者間で負荷分散を促進)をサポートします。

これは、シンプルさ、低遅延、高パフォーマンス、スケーラビリティを考慮して設計されています。低遅延と高スループットを必要とするシナリオでは非常に優れたパフォーマンスを発揮します。ただし、コアNATS単体では非保証配送のみを提供し、すなわちメッセージはアクティブな購読者にのみ配信されます。購読者がオフラインの場合、データは失われます。コアNATSは、耐久性よりもスピードとスケールが優先される場合に良い選択肢です。

JetStream

JetStreamはCore NATSの上に永続性機能を提供します。これにより、メッセージの耐久性と信頼性が向上しました。メッセージやイベントを永続化(ディスクまたはメモリ)し、再生することができます。永続化されたメッセージは、新規または復旧中の購読者に再生することができます。JetStreamを使用することで、ユーザーは追加の機能を得られます:

  1. ストリーム保持:メッセージがどのくらいの期間保持されるか。サイズ、時間、または消費者の制限に基づくことができます。
  2. 消費者の耐久性:消費者が中断した場所から再開できるようにします。
  3. メッセージの確認:これにより、配信の信頼性が保証されます。

JetStreamはCore NATSに複雑さの層を追加します。しかし、これにより、保証された配信、永続性、再生可能性のユースケースをサポートする重要な機能がもたらされます。

Kafka

Kafkaは、ログベースのブローカーアーキテクチャに基づいた分散メッセージングシステムです。Kafkaのデータはトピックに整理され、複数のパーティションを持つことができます。コンシューマはこれらのパーティションに接続されます。このアーキテクチャにより、Kafkaは単一のトピックに対してメッセージ消費を並列化できます。データはトピック/パーティションに順次追加されます。Kafkaはパーティション内の順序を保証します。Kafkaクラスタ内には、多くのブローカーが存在し、それぞれがトピックとパーティションのリストを管理しています。高可用性を達成し、データ損失を防ぐために、Kafkaはレプリケーションファクターに依存しており、パーティションは複数のKafkaブローカーに複製されます。このように、高スループット、フォールトトレランス、データ保持、および水平スケーラビリティを実現するために管理しなければならない複数のコンポーネントが存在します。これにより、Kafkaのアーキテクチャの複雑さが増します。

2. 高可用性とパフォーマンス

NATS

クラスタ内のすべてのノードはメッシュで相互接続されており、クライアントは任意のノードに接続できます。この構成により、単一障害点を回避できます。1つのノードが失敗した場合、クライアントは手動介入なしに自動的に他のノードに接続されます。これをNATSでは自己修復と呼びます。JetStream対応ノードは、ストリームをすべてのノードに分配します。ストリームは高度に管理され、メッシュクラスタ内のJetStream対応ノード間で負荷分散されます。

JetStreamは、複数のクラスタまたはノード間でのデータミラーリングもサポートしています。JetStreamでは、ストリームごとにリーダーが選出されます。各ストリームのレプリケーションは構成可能です。これらすべての要素がNATSにおける耐久性と可用性を確保します。

Kafka

Kafkaの高可用性はレプリケーションに基づいています。各トピックは1つ以上のパーティションを持つことができます。各パーティションはKafkaブローカー間で複製されます。これによりデータの冗長性と可用性が確保されます。Kafkaはリーダー-フォローレプリケーションメカニズムを採用しています。リーダーが読み書きを担当し、フォロワーがデータの複製を行います。

Kafkaは各パーティションに対してISR(In Sync Replicas)と呼ばれるものを維持しています。リーダーが失敗した場合、ISRの1つがリーダーになります。クラスタメタデータの管理とリーダーの選出に関して、KafkaはZookeeper(新しいバージョンではKRaft)に依存しています。

Performance and Scalability
機能
NATS
Kafka
スループット
高遅延または低遅延。小さなメッセージに最適化
高スループットと大きなメッセージに最適化
スケーリング
クラスタリングによる水平スケーラビリティ
パーティショニングによる水平スケーラビリティ
レイテンシ
サブミリ秒
ミリ秒
Recovery and FAILOver
特徴
NATS
Kafka
フェイルオーバー時間
サブセカンド(クライアントがより速く再接続)
遅い(リーダー選出プロセスに依存)
シームレスなリカバリー
クライアントは中断なく自動的に接続します
リーダー選出中に一部のダウンタイムが発生します
データ損失リスク
複製(JetStream)で最小限
複製およびISRが構成されている場合は最小限

3. メッセージパターン

NATS

NATSは、サブジェクトベースのメッセージングを使用しています。これにより、サービスやストリームはPub-Sub、リクエスト-リプライ、キューサブスクライバーパターンを使用できます。NATSのサブジェクトは階層構造とワイルドカードを使って構成できます。1つのNATSストリームは複数のサブジェクトを格納でき、クライアントアプリケーションはサーバーサイドのフィルタリングを使用して興味のあるサブジェクトのみを受信できます。NATSの接続は双方向で、クライアントは同時に発行と購読を行うことができます。NATSはRabbitMQに非常に似たキューイングもサポートしています。

Kafka

KafkaのストリームはPub-Subおよびトピックベースのメッセージングをサポートしています。負荷分散はコンシューマグループとトピックのパーティション化を通じて実現できます。

4. 配信保証

NATS

NATSはさまざまな配信保証をサポートしています。NATS単体では、最大1回の配信保証をサポートできます。JetStreamが有効なNATSサーバーは、追加の2種類の保証をサポートできます。それは「少なくとも1回」と「正確に1回」の保証です。NATSは個々のメッセージに「ack」を送信できます。サポートされているさまざまな「ack」については、NATSの公式ドキュメントを参照してください。「ack」のタイプに基づいて、NATSはメッセージを再配信できます。

Kafka

Kafkaは少なくとも1回と正確に1回の保証をサポートしています。メッセージの順序はパーティションレベルで保証されています。グローバルな順序付けはKafkaでは不可能です。

5. メッセージの保持と永続性

NATS

NATSはメモリおよびファイルベースの永続性をサポートしています。メッセージの再送信にはいくつかのオプションがあります。メッセージの再送信は、時間、カウント、またはシーケンス番号によって行うことができます。

Kafka

KAFKAはファイルベースの永続化のみをサポートしています。メッセージは最新、最初、または特定のオフセットから再生できます。KAFKAではログコンパクションがサポートされています。

6. 言語とプラットフォーム

NATS

48種類の既知のクライアントタイプ。GOLANGをサポートするアーキテクチャはすべてNATSサーバをサポートできます。

Kafka

18種類の既知のクライアントタイプ。KafkaサーバはJVMをサポートするプラットフォームで実行できます。

ユースケース

ユースケース1

要件

ストリーミングパイプラインを持つデータプラットフォームがあります。このプラットフォームはリアルタイムストリーミングにApache Flinkエンジンを使用し、アナリティクスパイプラインの作成にはApache Beamを使用しています。以下は主な要件です:

  1. 高スループットと低レイテンシのメッセージ処理
  2. チェックポイントとバックプレッシャのハンドリングのサポート
  3. MB単位のメッセージ処理
  4. メッセージの耐久性と永続性

比較

Kafkaの利点s:

  • 高スループット
  • 設定可能な保持ポリシーとデータの複製によるデータ保持
  • 少なくとも1つのメッセージ配信保証のサポート
  • 最初/最新/特定オフセットからのメッセージの読み取り
  • 信頼性のある配信のためのサーバーサイドの‘acks’
  • 大規模なデータストリームと大きなメッセージサイズの処理
  • コンパクショントピックのサポート

Kafkaの欠点:

  • 高リソース使用。私たちのクラスターはオンプレミスでリソースが制約されていました
  • Kafkaはほぼリアルタイムです

NATSの利点:

  • 最小限のリソース使用で高パフォーマンス。私たちのものはリソース制約のあるオンプレミスクラスターです
  • 少なくとも一度のサポート。我々は少なくとも一度の保証を探していました
  • 低遅延メッセージ処理

NATSの欠点:

  • Flink/Beam用のコネクタがないため、統合が困難でした
  • メッセージサイズによるパフォーマンス低下

最終決定

慎重な分析の結果、Kafkaが選ばれました。リソース使用とKafkaが提供する他の利点、特にApache BeamとFlinkとの良好な統合の間でトレードオフをしなければなりませんでした。Kafkaのもう一つの利点は、大きなメッセージサイズと高スループットのメッセージ処理を扱う能力です。

ユースケース2

要件

オンプレミスクラスターで生成されたイベントを処理すること、例:監査ログ。イベントは低遅延で処理されるべきです。また、マイクロサービス間の通信をサポートする必要があります。耐久性と永続性は要件ではありませんでした。メッセージサイズは小さかったです。イベントに対して分析を行う必要はありませんでした。私たちは制約のある環境にいました。リソース使用とメモリフットプリントは最小限であるべきです。

決定

NATSが選ばれた理由:

  • 効率的なリソース使用
  • 低遅延のイベント処理。
  • Goアプリケーションであるため、メモリフットプリントは非常に小さい
  • 小さなメッセージサイズを処理できる能力
  • マイクロサービス間の通信を支援するリクエスト-リプライサポート
  • JetStreamが構成されていない場合、メッセージは保存されません

Kafkaが選択されなかった理由:

  • デフォルトでは、メッセージはディスクに保存されます
  • リソース使用量がNATSと比較して高い
  • JVMが必要なため、メモリフットプリントが非常に大きい

要約

KafkaとNATSの選択は、アーキテクチャと複雑さ、パフォーマンスとスケーラビリティ、メッセージの配信保証という3つの主要領域にわたる具体的な要件に依存します。Kafkaは、堅牢なイベントストリーミング、耐久性のあるストレージ、高度な処理機能が必要なシステムに最適ですが、複雑さが高いです。一方、NATSは軽量で管理しやすく、シンプルなメッセージングニーズに適している低遅延、高スループットのシナリオで優れています。

分散メッセージングシステムを設計する際には、これらの領域を慎重に評価し、選択をアプリケーションの目標と制約に合わせるようにしてください。KafkaとNATSはどちらも強力なツールであり、適切な選択はユースケースに依存します。

KafkaとNATSの選択をする前に考慮すべき主要な領域:

  1. アーキテクチャと複雑さ
  2. 高可用性とパフォーマンス
  3. メッセージの配信保証

Kafkaは、イベントストリーミング、耐久性のあるストレージ、および進化する処理能力を必要とする分散システムに最適です。しかし、Kafkaは高いリソース使用量とメモリフットプリントを伴います。また、管理の複雑さはNATSと比較して非常に高いです。

一方、NATSは軽量で管理が簡単です。低遅延のメッセージ処理はNATSの特徴的な機能です。

最終的には、KafkaとNATSの両方が強力なイベント処理ツールです。選択は特定のユースケースに依存します。

Source:
https://dzone.com/articles/kafka-vs-nats-message-processing