技術(tech)

Kafka – Topicの__consumer_offsetsのキーとなるtopicName, partitionNumber, groupIdについて

この記事ではTopicの __consumer_offsets のキーとなるtopicName, partitionNumber, groupIdについて調査し紹介します。

背景

以下の記事にて、Debeziumの運用時に気にするポイントについて説明しました。

Debezium運用上の停止/起動の気になるポイントと対策Debezium運用上の停止/起動の気になるポイントと対策 DBのデータの変更をウォッチし、メッセージを送信出来るDebeziumですが...

その際に、KafkaのTopicという概念が出てきました。

Kafkaでは __consumer_offsets というようなトピックを持っていて、各Subscriberがどこまでのメッセージを消費したのかのオフセットを持っているとのことでした。

この__consumer_offsets は [topicName, partitionNumber, groupId] のキーで同様のSubscriberかどうかを判定しているようです。

さて、ここで疑問が湧きます。
キーとなっている [topicName, partitionNumber, groupId]って具体的に何なんだろうか。

今回はこれについて調べ、イメージ図を作成します。

対象者

  • Topicの概念イメージの解像度を少しだけ高めたい

イメージ

私の調査以前のKafkaのTopicに対する解像度は以下の通り。

「TopicにはProducerから送信されたMessageが保持されている」程度の理解です。

topicNameとpartitionNumber

これは、Topicの解像度を少しだけ高くするとpartitionNumberが何なのかが見えてきます。

Topicの1つを掘り下げてみると以下のようなイメージです。

以下の記事中での説明がとても分かりやすかったです。
https://qiita.com/sigmalist/items/5a26ab519cbdf1e07af3

  • 1つのTopic > 複数のPartitionで構成
  • 各Kafka ServerにBrokerが存在し、各PartitionはBroker間で複製されたReplicaで構成
    • ※ 耐障害性を高めるためにKafkaをCluster構成にした前提

つまり、Producer(例えばDebezium)から送られたMessageはKafkaの該当Topic内の各Partitionに保持されます。
もう少し細かく言うと、Messageは各Partitionの Leader replica のBroker上
に保持された後に、その他の Follower replica のBroker上にReplicateされます。

各Consumerは特定のPartitionをウォッチして、新しいMessageをTopicから取得します。

ここまでで、__consumer_offsets のキーとなっているtopicNameとpartitionNumberのイメージは少し湧いたかと思います。

groupId

残りは groupId とは何なのかです。

これは Consumer group の事を指しています。
Consumer側は1つ以上のConsumerから成るConsumer Groupを構成出来ます。

1つのConsumerが1のPartitionのみからMessageを読み込むよりも、Messageの読み込みを各Partitionに分散させたほうが、より効率的で早いよね的なイメージです。
また、Consumerも1つだけではなく、複数のConsumerが複数のPartitionからMessageを並列で読み込む事ができます。

更に、同一のConsumer Group内で重複したMessageの読み込みも基本的には発生しないようになっているようです。

例えば、TopicのPartitionが3つ、Consumerが2つのConsumer Groupが構成されている場合のイメージは以下の通りです。
※ ラウンドロビンでTopicのメッセージが処理される場合

Topic内のメッセージが分散的に読み込まれ、Consumer側でも分散して処理されることで、より効率的にメッセージがConsumeされます。

※ Partition側に対してラウンドロビンなのか、Consumerに対してラウンドロビンなのかは裏取りして確証を持っている訳では無く、私の理解が間違っていたらごめんなさい…

なお、具体的な検証内容も含めて、以下の記事がとても参考になりました。
https://pppurple.hatenablog.com/entry/2018/11/20/213651

こちらもまたまたお世話になりました。
https://qiita.com/sigmalist/items/3b512e2ab49b07271665#consumer-group%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

ここまでで、__consumer_offsets の各キーのイメージが少し湧いたかと思います。

__consumer_offsetsのキー

これで、以下の問いに対する解像度が少しは高くなりました。

キーとなっている[topicName, partitionNumber, groupId]って具体的に何なんだろうか。

どの Consumer Group が何の Topic の どの Partition を読んでいるのかがキーとなっているわけですね。

まとめ

今回は、Topicの解像度を高めるために頭の中を整理して、イメージ図に起こしてみました。

今回は色んな記事を漁りつつ、論理的なイメージを整理しただけの話でした。
なので、この記事の信頼性は高く無いです(話半分で見ていただけると幸いです)。

次は具体的に検証して確かめられればと思います。

ここまで見ていただき、ありがとうございました。

参考資料

本記事執筆にあたって、色んなドキュメントや記事を参考にさせていただきました(正直、私の記事よりも解像度が高いです…)。