Kafkaのメッセージング方式の特長を学び直した

自社サービスでKafkaを使っており、自分でも少し触ったことがあるのだが、Kafkaというのがメッセージングにおいてどんな特長を持ったサービスなのかについては、topicを介してproducerとconsumerがメッセージをやり取りする、という程度の理解しかなかった。これではいけないと思い、年末年始に公式ドキュメントを読み直したのでまとめておく。

kafka.apache.org

メッセージングサービスの大まかな分類

世の中のメッセージングサービスのモデルにはいろいろあるが、最もよくあるモデルはqueueとpub-subだろう。
queueモデルは、複数のconsumerがqueue内のレコードを読むが、それぞれのレコードは1つのconsumerの所にしか行かない。queueから出したらもうそのレコードはqueueの中にはない。
対してpub-subモデルは、複数のconsumerそれぞれに全レコードが配信される。ラジオの放送局が流す電波をどのラジオでも受け取って放送を聴けるように、1つのconsumerがレコードを受け取っても、そのレコードは他のconsumerも受け取ることができる。

これらのモデルには一長一短がある。queueモデルの場合、複数のconsumerを用意するだけで簡単に処理速度を上げることができる。しかし、1つのrecordは1つのconsumerにしか行かないので、障害発生時にデータロストしやすい。また、queueから渡される時点ではデータは順序どおりだが、各consumerは非同期で処理を行っているので、受け取る際にはデータの順序が入れ替わってしまったり、重複して受け取られてしまったりする可能性がある。
これに対してpub-subモデルの場合、どのconsumerも全データを受け取ることができるので、障害にも比較的強い。しかし、consumerの数を増やしても処理速度に跳ねにくい。

Kafkaの特長

Kafkaはqueueモデルとpub-subモデルを合わせ持ったような性質がある。まず、Kafkaは複数のconsumerをconsumer groupとして論理的に区分けすることができる。そして、同じconsumer group内のinstanceに対しては、recordはロードバランシングされる。違うconsumer groupには、それぞれに対して全recordが送られる。
すなわち、同じconsumer group内のconsumer instance同士では、queueモデルのようにレコードを読む処理を分担できる。一方で、異なるconsumer groupの間ではpub-subが成り立っている。

またKafkaの場合、topic内に複数のpartitionを持っている。topicは論理的な区分けでしかなく、partitionが物理的な区分けである。(そのため、1topic内のpartitionが複数のサーバに分離していることもある)
そしてconsumer groupに対し、1つのpartitionを1つのconsumer instanceに割り当てている。

f:id:Udomomo:20200105220629p:plain

(出典: https://kafka.apache.org/intro)

これにより、各partitionを読むconsumerが1つだけになり、各partiton内のデータは必ず順序通りconsumeされる。(もちろん、複数のpartition間の順序は保証されない)
なお、この方法の制約として、consumerがpartitionの数以上存在することはできない。