kafka topic, partition説明(producer, consumer, replication- factor, offset)
こんにちはcodeshowです。
今回はkafkaのtopicとpartitionについて学びます。
kafkaを使用するには必ずtopicが必要です。
このtopicを基準にproducerはメッセージをpublishし、
consumerはメッセージを購読します。
topicを生成するためにkafka を実行します。
環境設定は前の画像を参照してください。
kafka練習のためのdevcontainersを実行してください。
container実行されるまでお待ちください。
containerが実行されたらdocker desktop を開きます。
kafka containerでshellを実行します。
topic照会はkafka topicsのlist option を使用します。
kafka-topics --bootstrap-server kafka:9092 --list
基本的に生成されているtopic consumer offsetsとschemasを除いてtopicがないことを確認しました。
kafka- topics命令のcreate option を使用してtopicを生成します。
kafka-topics --bootstrap-server kafka:9092 --create --topic hello --partitions 1 --replication-factor 1
kafka topicsコマンドでhelloという名前でtopic を生成しました。
topicの名前はname option を使用して指定します。
replication factor optionは、 partitionデータをいくつのコピーを作成するかを選択するoptionです。
kafkaノードの数だけレプリカfactor値を設定しました。
値が高いほど、ノード間でパーティションのコピーコストが発生し、パフォーマンスに影響を与えます。
代わりに値が少ないと、 kafka障害時にデータが失われる可能性があります。
通常3以上の値をお勧めします。
ちなみに、 create時にkafkaノードの数よりも多くのreplicationfactorを入れるとエラーが発生します。
kafka-topics --bootstrap-server kafka:9092 --create --topic error --partitions 1 --replication-factor 4
別のoptionでpartitionsについて説明します。
partitionはkafkaの非常に重要な情報です。
partitions optionは、 topicをいくつに分割するかを設定する情報です。
もしproducerが 100 個のtopicをpublishし、このtopicは 1 個のpartitionしかないなら、
100 のtopicは 1 つのpartitionに積み上げられます。
もしconsumerが 1 つのtopicを処理するのに 1 分かかる場合。
topic 100個を処理するのに100分かかります。
partitionを 4 つに設定すると、 topicは 4 つのパーティションのそれぞれ 25 個ずつ積み重ねられます。
1 つのpartitionには最大 1 つのconsumerだけを置くことができるので、
これで、パーティションの数を増やすだけで3つのconsumerを追加できます。
処理時間を100分から25分に1/4短縮できます。
これまでの内容をshellを使って実習します。
hello topicにproducerとconsumerを練習します。
kafka containerからterminal を実行します。
左側にはproducer、右側にはconsumerを配置します。
kafka console producerコマンドを使用してkafkaに接続します。
kafka-console-producer --bootstrap-server kafka:9092 --topic hello
producerがkafka brokerに接続しました。
kafka console consumerコマンドを使用してkafkaに接続します。
partitionは 0 回 index から順次増加します。
実習ではpartition sizeが 1 なので、0 回partitionのみ使用可能です。
optionとしてpartition数値 0 を入力します。
kafka-console-consumer --bootstrap-server kafka:9092 --topic hello --partition 0
producerにhello messageと入力します。
consumerでhelloを確認できます。
では、一つのpartitionには複数のconsumerが接続できますか?
terminalをさらに実行し、 consumerを追加します。
kafka-console-consumer --bootstrap-server kafka:9092 --topic hello --partition 0
consumerは問題なく接続されます。
では、 producerでメッセージをpublishするとどうなりますか?
2つのシナリオがあります。
- consumer順に1回ずつ順次メッセージを渡します。
これをround robin方式と呼びます。 - すべてのconsumerからすべてのメッセージを転送します。
名前はbroadcastingと呼ばれます。
動作を確認するには、 producerとして hello1 メッセージを入力します。
2 つのconsumerにすべて hello1 メッセージが出ます。
再度producerとして hello2 メッセージを入力します。
2 つのconsumerにすべて hello2 メッセージが出ます。
kafkaは、同じpartitionに接続されているすべてのconsumerがbroadcasting方式でメッセージを受け取ります。
ちなみに、異なるmessagebrokerであるrabbit mqは、1つのqueueに複数のworkerを関連付けることができます。
そしてround robinでworkerはメッセージを順次メッセージを受け取ります。
この部分がkafkaと動作が異なり、 rabbit mqを最初に経験した人は混乱する可能性があります。
rabbit mqは 1 つのqueueにworkerのsizeを増やしてスループットを増やし、
kafkaは 1 つのtopicのpartition sizeを増やしてスループットを増やします。
今回の実習ではpartitionの数を変更します。
partitionの数を1から2に増やします。
ctrl cを押してproducerを終了します。
kafka topics命令のalter optionを使ってpartition sizeを 2 に増やします。
kafka-topics --bootstrap-server kafka:9092 --alter --partitions 2 --topic hello
kafka topicsのdescribeオプションでパーティション情報を確認します。
kafka-topics --bootstrap-server kafka:9092 --topic hello --describe
ちなみに、 AKHQのtopic画面でも増えたpartition size 2 を確認できます。
再度producerを実行し、新しく追加された 1 回partitionにconsumerを追加します。
kafka-console-producer --bootstrap-server kafka:9092 --topic hello
既存のpartition 0 に接続されたconsumerを終了し、新たにpartition 1 にconsumerを接続します。
kafka-console-consumer --bootstrap-server kafka:9092 --topic hello --partition 0
kafka-console-consumer --bootstrap-server kafka:9092 --topic hello --partition 1
producerでランダムに複数回メッセージを作成します。
consumerは 2 つですが、 topicは 1 consumerにのみ分けて渡されます。
これは、keyがない場合にkafkaが機能するsticky partition cache方式です。
keyがない場合、最初に送ったpartition番号をcacheし、このpartitionにだけtopic を渡します。
keyがなければ、1 つのpartitionだけを使用するのでpartitionを増やしても意味がありません。
つまり、 keyはkafkaでtopicが保存されるpartitionを決定する重要な情報です。
partition間でtopicがよく分かれて保存されるようにkeyを追加します。
producerにproperty option を追加してやり直します。
kafka-console-producer --bootstrap-server kafka:9092 --topic hello --property "key.separator=-" --property "parse.key=true"
producerでランダムに値を入れてみましょう。
これで、 topicがpartitionに分割されて保存されていることを確認できます。
特に、同じkeyは同じpartitionでpublishされることをconsumerを通じて確認できます。
key separator option を利用して dash の前にはkey、後にはvalueがpublishされます。
a はkey、 b はvalueになります。
ちなみに、従来はkeyなしで、 helloというvalueのみpublishしました。
dash を基準に前の値が同じであればkeyが同じものです。
重要なのは、同じkeyは常に同じpartitionに格納されます。
ただし、keyが異なる場合は、同じpartitionまたは別のpartitionに保存されます。
この部分を理解するために、 kafkaでkeyを扱う方法を見てみましょう。
kafkaはkeyをhashしてkafkaノードの数だけ残りの演算をして出る結果値をpartition番号で決定します。
今はpartitionが 2 つなので、0 と 1 だけがpartition番号で出ることができます。
ちなみに、 hashアルゴリズムはmurmur2 hash を使用します。
partitionを理解する際の重要な点として、 kafkaはpartition単位でのみtopicの順序を保証します。
つまり、順序が重要なtopicをpublishするときは、同じpartitionに入れなければなりません。
key値は常に同じpartitionに保存されることを確認したので、
順序が重要なtopicの場合は、必ず同じkeyを使用してください!
次にpartitionのoffsetについて説明します。
kafkaが既存のmessage queueと異なる特徴としてはconsume後にqueueからメッセージを削除しません。
パーティションは配列に似ています。
partitionの中には、 topicは配列の要素のように順番に格納されています。
index で配列の値に近づくように、 offsetを使用してpartitionの特定の index 以降からconsumeを行うことができます。
ちなみにpartitionごとに最後のoffset を持っています。
そのため、新しいconsumerがoffsetoptionなしで接続されている場合は、最後のoffsetからconsumeを行います。
しかし、 offset option を与えると、 offset情報からconsumeを行います。
実習でterminalに 2 つのコマンドを出します。
- 0 番offsetからconsumerに実行を指示します。
- offsetコマンドなしでconsumerを実行するように指示します。
kafka-console-consumer --bootstrap-server kafka:9092 --topic hello --partition 1 --offset 0
kafka-console-consumer --bootstrap-server kafka:9092 --topic hello --partition 1
offset index 0 optionを与えると、最初からやり直すことを確認できます。
offset optionがない場合は、 offsetオプションのデフォルトはlatestです。
新しくpublishたtopicのみをconsumeます。
最後に、 partitionの重要な制約として、
partition sizeに従来より小さい値を入れることはできません。
partition sizeは、より大きな値のみ入力可能です。
partitionを2つから1つに減らすalterコマンドを発行します。
kafka-topics --bootstrap-server kafka:9092 --alter --partitions 1 --topic hello
partition option値に 2 より大きい値を入れるエラーメッセージを確認できます。
以上でkafkaのtopicとpartitionの説明を終えます。
次回はconsumer groupsの使い方を見てみましょう。
ちなみに、 consumerがpartitionを直接consumeより、
consumer groupsを実務でより多く使用します。
今回の授業はこのconsumer groupsをよく理解するため、
partitionを学習する時間がありました。
サブスクリプションといいね!通知設定は、コンテンツ制作者に多くの役に立ちます。
ありがとうございます。