新版Kafka已将consumer的位移信息保存在Kafka内部的topic中,即__consumer_offsets topic。如何将多个consumer组成消费者组?同时组成消费者组在消费消息时,对应的offset文件是如何变化的?本文的生产消费模型图如下,一个生产者生产,两个消费者消费:
#进入到zookeeper目录后,再启动zookeeper
bin/zkServer.sh start
#进入到kafka目录后,再启动kafka
bin/kafka-server-start.sh config/server.properties
#另启一个终端,进入到kafka目录后,创建一个名为topicC的topic
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 3 --topic topicC
#启动生产者
bin/kafka-console-producer.sh --broker-list localhost:9092 --topic topicC
想要把不同的消费者创建成一个消费者组,需要对配置文件进行修改,并且在命令行中指定该配置文件,否则命令行会默认执行--new-consumer,使得每个消费者单独组成消费者组
配置文件的路径:{kafka目录}/config/consumer.properties。我们将消费者组命名为topicCgroup
打开两个终端,使用相同的命令,启动两个消费者
#启动消费者,指定同一个配置文件,或者不同的配置文件中配置相同的group.id
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topicC --from-beginning --consumer.config config/consumer.properties
可以看到consumer1消费一个partition,consumer2消费两个partition
我们进行模拟,手动终止consumer1和consumer2,而生产者仍继续发送了11,12,13,14,15。然后在此时,我们再启动consumer,指定相同的group.id,即可继续消费
另有两点值得注意:
(1)消费顺序并不是11-12-13-14-15,这印证了topic中partition之间无序,partition内有序
(2)重启的消费者同时消费了所有的partition
要实现上述操作,那么有两个信息是kafka内部必然要存储的(1)消费者组id;(2)每个partition的offset。只有两者结合,才能明确某一个消费者组具体的消费进度。
在新版kafka中,用名为__consumer_offsets的topic来进行存储上述两个信息,默认的partition是50,因此在保存节点的文件夹中(同样可以在配置文件中指定节点的保存位置),可以看到
如何确定topicCgroup保存在哪个partition?依赖最早在consumer.properties中指定的group.id属性,本文就为topicCgroup。如果忘记了自己的group.id,可以通过以下命令查询
#获取该consumer group的group id
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list --new-consumer
通过计算器计算,公式如下 ,numPartitions默认为50
Math.abs(groupID.hashCode()) % numPartitions
比如topicCgroup的计算结果就为45。说明在__consumer_offset-45这个partition中。然后,我们就可查看该partition的位移信息
#获取指定consumer group的位移信息
bin/kafka-simple-consumer-shell.sh -topic __consumer_offsets --partition 45 --broker-list localhost:9092 --formatter "kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter"
查询结果如下,一开始只有10条消息,所以partition0,1,2的offset分别为4,3,3。在消费者重新启动后,消息共有15条,所以partition0的offset从4更新到5,partition1的offset从3更新到5,partition2的offset从3更新到5。从结果上看,就是把之前未消费的5条消息消费了。