由于 Zookeeper 并不适合大批量的频繁写入操作,新版 Kafka 已推荐将 consumer 的位移信息保存在 Kafka 内部的 topic 中,即__consumer_offsets topic,并且默认提供了kafka_consumer_groups.sh脚本供用户查看 consumer 信息。
不过依然有很多用户希望了解__consumer_offsets topic内部到底保存了什么信息,特别是想查询某些 consumer group 的位移是如何在该 topic 中保存的。针对这些问题,本文将结合一个实例探讨如何使用 kafka-simple-consumer-shell 脚本来查询该内部 topic。
创建 topic “test”
bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic test --replication-factor 3 --partitions 3
使用 脚本生产消息
由于默认没有指定 key,所以根据 round-robin 方式,消息分布到不同的分区上。
验证消息生产成功
bin/ kafka.tools.GetOffsetShell --broker-list localhost:9092,localhost:9093,localhost:9094 --topic test --time -1
结果输出表明 64 条消息全部生产成功!
test:2:21
test:1:21
test:0:22
创建一个 console consumer group
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092,localhost:9093,localhost:9094 --topic test --from-beginning --new-consumer
获取该 consumer group 的 group id(后面需要根据该 id 查询它的位移信息)
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092,localhost:9093,localhost:9094 --list --new-consumer
查询__consumer_offsets topic 所有内容
bin/kafka-console-consumer.sh --topic __consumer_offsets --zookeeper localhost:2181 --formatter “kafka.coordinator.group.GroupMetadataManager$OffsetsMessageFormatter” --consumer.config config/consumer.properties --from-beginning
默认情况下__consumer_offsets有 50 个分区,如果你的系统中 consumer group 也很多的话,那么这个命令的输出结果会很多。
计算指定 consumer group 在__consumer_offsets topic 中分区信息
这时候就用到了第 5 步获取的 group.id(本例中是 console-consumer-46965)。Kafka 会使用下面公式计算该 group 位移保存在__consumer_offsets的哪个分区上:
Math.abs(groupID.hashCode()) % numPartitions
所以在本例中,对应的分区=Math.abs(“console-consumer-46965”.hashCode()) % 50 = 11,即__consumer_offsets的分区 11 保存了这个 consumer group 的位移信息,下面让我们验证一下。
获取指定 consumer group 的位移信息
bin/ --topic __consumer_offsets --partition 11 --broker-list localhost:9092,localhost:9093,localhost:9094 --formatter “kafka.coordinator.group.GroupMetadataManager$OffsetsMessageFormatter”
下面是输出结果:
[console-consumer-46965,test,2]::[OffsetMetadata[21,NO_METADATA],CommitTime 1479092279434,ExpirationTime 1479178679434]
[console-consumer-46965,test,1]::[OffsetMetadata[21,NO_METADATA],CommitTime 1479092284246,ExpirationTime 1479178684246]
[console-consumer-46965,test,0]::[OffsetMetadata[22,NO_METADATA],CommitTime 1479092284246,ExpirationTime 1479178684246]
[console-consumer-46965,test,2]::[OffsetMetadata[21,NO_METADATA],CommitTime 1479092284246,ExpirationTime 1479178684246]
[console-consumer-46965,test,1]::[OffsetMetadata[21,NO_METADATA],CommitTime 1479092284436,ExpirationTime 1479178684436]
[console-consumer-46965,test,0]::[OffsetMetadata[22,NO_METADATA],CommitTime 1479092284436,ExpirationTime 1479178684436]
[console-consumer-46965,test,2]::[OffsetMetadata[21,NO_METADATA],CommitTime 1479092284436,ExpirationTime 1479178684436]
该 consumer group 果然保存在分区 11 上,且位移信息都是对的 (这里的位移信息是已消费的位移,严格来说不是第 3 步中的位移。由于我的 consumer 已经消费完了所有的消息,所以这里的位移与第 3 步中的位移相同)。另外,可以看到__consumer_offsets topic 的每一日志项的格式都是:[Group, Topic, Partition]::[OffsetMetadata[Offset, Metadata], CommitTime, ExpirationTime]。
















