Kafka中Consumer Group

Consumer Group 是 Kafka 提供的可扩展且具有容错性的消费者机制。

  1. Consumer Group 下可以有一个或多个 Consumer 实例。这里的实例可以是一个单独的进程,也可以是同一进程下的线程。在实际场景中,使用进程更为常见一些。
  2. Group ID 是一个字符串,在一个 Kafka 集群中,它标识唯一的一个 Consumer Group。
  3. Consumer Group 下所有实例订阅的主题的单个分区,只能分配给组内的某个 Consumer 实例消费。这个分区当然也可以被其他的 Group 消费。

理想情况下,Consumer 实例的数量应该等于该 Group 订阅主题的分区总数。

 设置大于总分区数的 Consumer 实例只会浪费资源,而没有任何好处,因为一个partition只能被同一个consumer group中的一个消费者消费。

有几个问题

1.针对 Consumer Group,Kafka 是怎么管理位移的呢?

对于 Consumer Group ,Offset是一组 KV 对,Key 是分区,V 对应 Consumer 消费该分区的最新位移。

老版本的 Consumer Group 把位移保存在 ZooKeeper 中,因为比较流行的提法是将服务器节点做成无状态的,这样可以自由地扩缩容,实现超强的伸缩性,存储的格式路径是/kafka/consumers/consumer group名字/offsets/topic名字/partition,内容就是消费的offset值。

使用的java类是kafka.javaapi.consumer.ConsumerConnector

/kafka/consumers/zoo-consumer-group/offsets/my-topic/0

但是ZooKeeper 这类元框架其实并不适合进行频繁的写更新,而 Consumer Group 的位移更新却是一个非常频繁的操作。这种大吞吐量的写操作会极大地拖慢 ZooKeeper 集群的性能,所以新版的kafka不再使用zk,采用了将位移保存在 Kafka 内部主题的方法。

这个Broker 端内部主题就是 __consumer_offsets。配置参数【bootstrap.servers】来消费。

当 Kafka 集群中的第一个 Consumer 程序启动时,Kafka 会自动创建位移主题。分区数,副本数或备份因子是怎么控制的呢?答案也很简单,这就是 Broker 端参数 offsets.topic.replication.factor 和offsets.topic.num.partitions要做的事情了。它的默认值是 3。自动创建的,那么该主题的分区数是 50,副本数是 3。最好不要自己手工改,因为有些hardcode用了这些数字。

使用的java类是org.apache.kafka.clients.consumer.KafkaConsumer

用kafka-consumer-offset-checker查看

[root@localhost data]# kafka-consumer-offset-checker --zookeeper localhost :2181/kafka --group test-consumer-group --topic stable-test
[2017-08-22 19:24:24,222] WARN WARNING: ConsumerOffsetChecker is deprecated and will be dropped in releases following 0.9.0. Use ConsumerGroupCommand instead. (kafka.tools.ConsumerOffsetChecker$)
Group Topic Pid Offset logSize Lag Owner
test-consumer-group stable-test 0 601808 601808 0 none
test-consumer-group stable-test 1 602826 602828 2 none
test-consumer-group stable-test 2 602136 602136 0 none

 

上面结果的说明:

Group : 消费者组
Topic : topic的名字
Pid : partition的ID
Offset : kafka消费者在对应分区上已经消费的消息数【位置】
logSize : 已经写到该分区的消息数【位置】
Lag : 还有多少消息未读取(Lag = logSize - Offset)
Owner : 分区创建在哪个broker

 

虽说位移主题是一个普通的 Kafka 主题,但它的消息格式却是 Kafka 自己定义的,用户不能修改,也就是说你不能随意地向这个主题写消息,因为一旦你写入的消息不满足 Kafka 规定的格式,那么 Kafka 内部无法成功解析,就会造成 Broker 的崩溃。事实上,Kafka Consumer 有 API 帮你提交位移,也就是向位移主题写消息。这个位移主题,保存的offset信息也是一个KV,位移主题的 Key 中应该保存 3 部分内容:<Group ID,主题名,分区号 >。除了offset的消息,这个主题还有2种消息格式:

  1. 用于保存 Consumer Group 信息的消息。(用来注册 Consumer Group )
  2. 用于删除 Group 过期位移甚至是删除 Group 的消息。(tombstone 消息,即墓碑消息,也称 delete mark。是空消息体。一旦某个 Consumer Group 下的所有 Consumer 实例都停止了,而且它们的位移数据都已被删除时,Kafka 会向位移主题的对应分区写入 tombstone 消息,表明要彻底删除这个 Group 的信息。)

 

2.如果两个消费者 Topic 不一样,但是 GroupName 一样,会出现什么现象?

RocketMQ 有这个问题,好像是部分消息才会消费。

Kafka从上面的存储格式来看,不会出现该问题,因为topic是分开的存储offset的。

consumer.subscribe(Pattern.compile("sales-.*");或者consumer.subscribe(Set<String>);这样就可以订阅多个主题。

Kafka是没影响的。

 

3.Kafka有两种提交方法,自动提交位移和手动提交位移,这个对于位移主题有什么影响?

自动提交位移,enable.auto.commit =  true,则 Consumer 在后台默默地为你定期提交位移,提交间隔由一个专属的参数 auto.commit.interval.ms 来控制。自动提交位移有一个显著的优点,就是省事,你不用操心位移提交的事情,就能保证消息消费不会丢失。但这一点同时也是缺点,只要 Consumer 一直启动着,它就会无限期地向位移主题写入消息。

手动提交位移,即设置 enable.auto.commit = false。一旦设置了 false,作为 Consumer 应用开发的你就要承担起位移提交的责任。Kafka Consumer API 为你提供了位移提交的方法,如 consumer.commitSync 等。当调用这些方法时,Kafka 会向位移主题写入相应的消息。

 

当然Kafka 使用Compact 策略来删除位移主题中的过期消息,避免该主题无限期膨胀,Compact 的过程就是扫描日志的所有消息,剔除那些过期的消息,然后把剩下的消息整理在一起。

Kafka 提供了专门的后台线程定期地巡检待 Compact 的主题,看看是否存在满足条件的可删除数据。这个后台线程叫 Log Cleaner。很多实际生产环境中都出现过位移主题无限膨胀占用过多磁盘空间的问题,如果你的环境中也有这个问题,我建议你去检查一下 Log Cleaner 线程的状态,通常都是这个线程挂掉了导致的。

 

posted @   klm-kain  阅读(715)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示