web-dev-qa-db-ja.com

ApacheではKafka=パーティションよりも多くのコンシューマーインスタンスが存在できないのはなぜですか?

私はここで紹介セクションを読んで、カフカについて学んでいます

https://kafka.Apache.org/documentation.html#introduction

特に消費者に関する部分。はじめの最後から2番目の段落には、

Kafkaの方が優れています。 Kafkaは、トピック内での並列処理という概念を使用することにより、コンシューマプロセスのプールで順序付けの保証と負荷分散の両方を提供できます。これは、これにより、コンシューマーがそのパーティションの唯一のリーダーであり、データを順番に消費することが保証されます。多くのパーティションがあるため、それでも多くのコンシューマインスタンスで負荷を分散しますが、パーティションよりも多くのコンシューマインスタンスは存在できないことに注意してください。

筆者が2つの消費者グループと4つのパーティションのトピックを描いている段落のすぐ上の画像には、パーティションよりも多くの消費者インスタンスがあるので、私の最後の文に混乱が生じています。

また、パーティションよりもコンシューマーインスタンスの数が多くないことも意味がありません。パーティションが非常に小さくなり、各コンシューマーインスタンスに新しいパーティションを作成する際のオーバーヘッドがKafkaを滞らせるためです。パーティションはフォールトトレランスと1台のサーバーの負荷を軽減するために使用されることを理解していますが、上記の文は、一度に数千のコンシューマーを処理できるはずの分散システムのコンテキストでは意味がありません。

52
almel

それを理解するには、いくつかの部分を理解する必要があります。

  1. 注文全体の注文を提供するために、メッセージは1人の消費者にのみ送信できます。そうしないと、次のメッセージを送信する前にすべてのコンシューマーがメッセージを受信するのを待つ必要があるため、非常に非効率的です。

ただし、サーバーはメッセージを順番に配布しますが、メッセージはコンシューマーに非同期で配信されるため、異なるコンシューマーに順番どおりに到着しない場合があります。これは、並列消費が存在すると、メッセージの順序が事実上失われることを意味します。メッセージングシステムは、1つのプロセスのみがキューから消費できるようにする「排他的コンシューマ」という概念を持つことで、この問題を回避することがよくありますが、もちろんこれは処理に並列性がないことを意味します。

Kafkaの方が優れています。 Kafkaは、トピック内での並列処理という概念を使用することにより、コンシューマプロセスのプールで順序付けの保証と負荷分散の両方を提供できます。これは、これにより、コンシューマーがそのパーティションの唯一のリーダーであり、データを順番に消費することが保証されます。多くのパーティションがあるため、それでも多くのコンシューマインスタンスで負荷を分散しますが、パーティションよりも多くのコンシューマインスタンスは存在できないことに注意してください。

Kafkaは、トピック内の異なるパーティション間ではなく、パーティション内のメッセージの全体的な順序のみを提供します。

Kafkaは、他のパーティションが終了するのを待っている間、異なるパーティションのアクションを完全に並行して実行できるため、パフォーマンスの低下(複数のパーティション)は実際にはパフォーマンスの向上です。

  1. この図はさまざまなコンシューマーグループを示していますが、パーティションごとに最大1つのコンシューマーの制限はグループ内のみです。あなたはまだ複数の消費者グループを持つことができます。

最初に、2つのシナリオについて説明します。

すべてのコンシューマーインスタンスが同じコンシューマーグループを持っている場合、これは、コンシューマーの負荷を分散する従来のキューのように機能します。

すべてのコンシューマインスタンスに異なるコンシューマグループがある場合、これはパブリッシュ/サブスクライブのように機能し、すべてのメッセージがすべてのコンシューマにブロードキャストされます。

そのため、kafka=はすべてのグループにメッセージを複製し、全体の順序を保証する必要があるため、サブスクライバグループが多いほどパフォーマンスが低下します。

一方で、グループが少なく、パーティションが多いほど、メッセージ処理の並列化から得られるものが多くなります。

53
peter

Kafka= [消費者グループ、トピック、パーティション]ごとに1つのオフセットを保持することを思い出してください。それが理由です。

私は文を推測する

ただし、パーティションよりも多くのコンシューマインスタンスは存在できないことに注意してください。

いくつかのコンシューマーをトピックのリストにサブスクライブするときのデフォルトのコンシューマーモードである「自動コンシューマーグループ再バランス」モードを指します。

少なくともKafka 0.9.xでは、同じパーティションから複数のコンシューマーインスタンス、同じグループのメンバーを読み取ることを妨げるものは何もないと思います。

2つ以上の異なるスレッドでこのようなことを行うことができます

Properties props = new Properties();
props.put(ConsumerConfig.GROUP_ID_CONFIG, "MyConsumerGroup");
props.put("enable.auto.commit", "false");
consumer = new KafkaConsumer<>(props);
TopicPartition partition0 = new TopicPartition("mytopic", 0);
consumer.assign(Arrays.asList(partition0));
ConsumerRecords<Integer, String> records = consumer.poll(1000);

また、同じパーティションから2人(またはそれ以上)のコンシューマが読み取りを行います。

さて、「問題」は、両方のコンシューマーが同じオフセットを共有することです。プレイするグループ、トピック、パーティションは1つしかないため、他のオプションはありません。

両方のコンシューマーが同時に現在のオフセットを読み取ると、両方のコンシューマーが同じ値を読み取り、両方のコンシューマーが同じメッセージを取得します。

各コンシューマに異なるメッセージを読み取らせたい場合は、一度に1人だけがオフセットをフェッチしてコミットできるように、それらを同期する必要があります。

5

Kafka=パーティションごとに複数のコンシューマをサポートできない理由があります。

Kafkaブローカーは、パーティションごとにファイルにデータを書き込みます。 2つのパーティションが構成されている場合、ブローカーは2つのファイルを作成し、メッセージを送信できる複数のコンシューマーグループを割り当てます。

現在、各パーティションについて、ファイルのオフセットに基づいてメッセージを消費するコンシューマは1つだけです。たとえば、コンシューマ1は最初にファイルオフセット0から4096のメッセージを読み取ります。これらのオフセットはペイロードの一部であるため、コンシューマは次のメッセージの読み取りを要求するときに使用するオフセットを認識します。

複数のコンシューマーが同じパーティションから読み取る場合、コンシューマー1はオフセット0-4096のファイルから読み取りますが、コンシューマー2は、コンシューマー1に送信されたメッセージも受信しない限り、オフセット0から読み取りを試みます。これは負荷分散ではないため、Kafka=はすべてのコンシューマグループがメッセージを受信できるようにそれらをコンシューマグループに分割しましたが、コンシューマグループ内では、1人のコンシューマのみがメッセージを受信できます。

2
rjoshi

Kafkaでは、1つのコンシューマインスタンスのみがパーティションからメッセージを消費できます。コンシューマインスタンスがパーティションより多い場合、余分なコンシューマインスタンスは使用されません。したがって、kafka=これらの余分なコンシューマーインスタンスを許可しないでください。

現在、複数のコンシューマがパーティションを消費できる場合、メッセージの消費に順序はありません。これが、kafkaパーティションごとに複数のコンシューマを許可しない理由です

1
Abhinav

Kafkaコンシューマーグループモデルは、1つのコンシューマーインスタンスによって一度読み取られたメッセージがすぐにキューから削除されるキューイングメカニズムと、保持期間が設定されるか期限が切れて利用可能になるまでメッセージが削除されないpub/subメカニズムのハイブリッドです有効期限までのすべてのコンシューマインスタンス。そのため、pub/subモデルを使用したいが、それをキューイングメカニズムとして利用したい場合は、すべてのコンシューマインスタンスのコンシューマグループを作成します。 Kafkaは、単一のコンシューマグループ内のコンシューマインスタンス間でパーティションを分散します。1つのメッセージが1回だけ処理されることが保証されます。Kafka単一の消費者グループ内のインスタンスは、消費者グループを持つという目的に反します。

この例を考えてみましょう:

REST API pub1は、part1からpart4までの4つのパーティションを持つtopic1に4つのメッセージを発行したため、各パートには1つのメッセージがあります。

サブスクライバーとして2つのマイクロサービスsub1とsub2があり、実行中の各マイクロサービスの4つのインスタンスがあります。

ここで、2つのコンシューマグループを作成すると、各miroservice sub1instance1に1つがpart1にマッピングされ、sub1instance2がpart2にマッピングされます。同様に、sub2instance1はpart1にマッピングされ、sub2instance2はpart2にマッピングされます。

各コンシューマグループ内のコンシューマインスタンスがパーティションの数以下である限り、マイクロサービスの各インスタンスはメッセージを1回だけ処理します。この場合、sub1instance1とsub2instanceはpart1からmsg1を処理します。

パーティションよりも多くのコンシューマインスタンスがある場合、Kafkaは同じパーティションを複数のコンシューマインスタンスに割り当てる必要があるため、そのパーティションにマッピングされた各コンシューマインスタンスによってメッセージが複数回処理されます。これが理由です。 why Kafka=は、コンシューマグループがサブスクライブしているトピック内のパーティションの数よりも多くのコンシューマインスタンスをコンシューマグループ内に持つことを防ぎます。

これが理にかなっていることを願っています。

1
kaycee