前言
消费组是kafka一个非常有意思的设计。在高并发方面,可以使用多个台服务器放在同一个消费组中,就可以保证所有的消费者拉取的消费不会重复并且完整,这样就可以提高消费者的执行效率。
前期准备
创建topic
kafka-topics.sh --zookeeper localhost:2181 --create --topic topic_demo --partitions 3 --replication-factor
请注意这里的partition数量为3,在后面的实验会产生影响
启动生产者和消费者
kafka-console-producer.sh --broker-list localhost:9092 --topic topic_demo
kafka-console-consumer.sh --zookeeper localhost:2181 --topic topic_demo --consumer-property group.id=group1
通过添加–consumer-property group.id=group1指定消费组为group1
1个生产者和3个消费者
三个消费者非常理想地将6条消息平均消费,每个消费者两条消息,组合起来就是所有的消息,保证了数据的完整性。
1个生产者和4个消费者
很出出乎意料的是,当分区数量是3,而消费者数量是4的时候,会有一个消费者拉取不到任何消息
来看看消费组的消费者情况,可以看到下图,有一个消费者是没有对应的partition的,所以它就拉取不到消息。因此,我们在建立topic的时候,可以多建一些分区,保证多个消费者都能对应到分区,避免有消费者被浪费。当然,在创建完topic后,利用命令kafka-reassign-partitions.sh是可以进行增加分区的。
1个生产者和2个消费者
当使用2个消费者的时候,同样出现了我们没有预料到的现象,那就是消费数据的没有被平均分配,而是一个是4条,一个是2条。原因就是一个消费者对应2个分区,另一个消费者对应一个分区,而消息的消费是根据分区进行平均消费的。
看一看此时的消费分组就更清楚了,下图中,partition0和partition1对应的consumer_id都是group1_Jeffrey.local-1538062744435-29ee459d。
在有些情况下,还会出现数据顺序不对,请看下图,有一个消费者拉取的消息是3265。
kafka的消息是按分区来存储的,只能保证分区上消息是按照顺序拉取(关于kafka存储可以参考我的另一个篇文章)。
下图显示的是消息存放的位置,producer将123456推送给broker,broker在消息分别存放在3个partition里面。partition0有消息3和6,partition1有消息2和5,partition2有消息1和4。consumer0消费了partition0和partition1中的消息,并且先消费的是partition0,就出现拉取的消息是3265了。
下图是kafka日志中消息的存放情况。
总结
同一个消费组的多个消费者相当于一个消费者去消费数据,提高了消费的效率。topic的分区,给消费顺序带来了一些麻烦,通过了解到kafka的底层原理后,在遇到问题时,就可能解释并解决。