Consumer Groups

消费者在取topic的消息时,可以从一个partition里读,也可以同时从多个partition里读:

image-20201206075140963

Consumer Groups

Consumer group是kafka提供的可扩展且具有容错性的消费者机制。组内可以有多个消费者,它们共享一个group ID,一起来消费主题的所有分区(partition)。一个topic的一个partition只能被一个consumer group中的一个consumer消费,多个consumer消费同一个partition中的数据是不允许的,一个consumer可以消费多个partition中的数据。

比如一个 topic,有2个分区 partition0、partition1。有一个消费者组,组内有2个消费者 customer0、customer1。消费者组中的customer0 和 customer1 只能 【各自】 消费该topic中某个分区的数据,比如customer0消费partition0,customer1消费partition1。

如果只有一个消费者 customer0,那么所有分区的数据都需要customer0 来消费(参考下图的consumer-group-3)。

image-20201206081935673


如果consumer的数量大于partition的数量,则有些consumer是空闲的:

image-20201206082030731


Consumer Offsets

消费者在消费的过程中需要记录自己消费了多少数据,即消费位置信息。在Kafka中这个位置信息有个专门的术语:位移(offset)。很多消息引擎都把这部分信息保存在服务器端(broker端)。

当consumer从Kafka读取数据时,它应当更新这个offset。提交offset主要是为了表征 Consumer 的消费进度,这样当 Consumer 发生故障重启之后,就能够从 Kafka 中读取之前提交的位移值,然后从相应的位移处继续消费,从而避免整个消费过程重来一遍。

image-20201206082557718

老版本的 Consumer Group 把位移保存在 ZooKeeper 中。不过,慢慢地人们发现了一个问题,即 ZooKeeper 这类元框架其实并不适合进行频繁的写更新,而 Consumer Group 的位移更新却是一个非常频繁的操作。这种大吞吐量的写操作会极大地拖慢 ZooKeeper 集群的性能

新版本的 Consumer Group 中,Kafka 社区重新设计了 Consumer Group 的位移管理方式——Kafka Topic存储着consumer当前读取到的offset,topic名称叫__consumer_offsets


__consumer_offsets

Consumer 的位移数据作为一条条普通的 Kafka 消息,提交到 __consumer_offsets 中。它要求这个提交过程不仅要实现高持久性,还要支持高频的写操作。显然,Kafka 的主题设计天然就满足这两个条件,因此,使用 Kafka 主题来保存位移这件事情

虽说__consumer_offsets是一个普通的 Kafka 主题,但它的消息格式却是 Kafka 自己定义的,用户不能修改,不能随意地向这个主题写消息,因为一旦写入的消息不满足 Kafka 规定的格式,那么 Kafka 内部无法成功解析,就会造成 Broker 的崩溃。事实上,Kafka Consumer 有 API 帮你提交位移,向__consumer_offsets写消息。你千万不要自己写个 Producer 随意向该主题发送消息。

位移的提交

Consumer 需要向 Kafka 汇报自己的位移数据,这个汇报过程被称为提交位移(Committing Offsets)。因为 Consumer 能够同时消费多个partition的数据,所以位移的提交实际上是在partition粒度上进行的,即 Consumer 需要为分配给它的每个partition提交各自的位移数据。

从用户角度来说,位移提交分为自动提交手动提交;从 Consumer 端的角度来说,位移提交分为同步提交异步提交

大数据组件都关闭了自动提交,采取了手动提交

自动提交位移

Consumer 端有个参数叫enable.auto.commit,如果值是 true,则 Consumer 在后台默默地为你定期提交位移,提交间隔由一个专属的参数 auto.commit.interval.ms来控制

Kafka 会保证在开始调用 poll 方法时,提交上次 poll 返回的所有消息。从顺序上来说,poll 方法的逻辑是先提交上一批消息的位移,再处理下一批消息,因此它能保证不出现消费丢失的情况。但自动提交位移的一个问题在于,它可能会出现重复消费,如果处理失败了下次开始的时候就会从上一次提交的offset 开始处理

手动提交位移: 很多与 Kafka 集成的大数据框架都是禁用自动提交位移的,如 Spark、Flink 等。这就引出了另一种位移提交方式:手动提交位移,即设置 enable.auto.commit = false

Kafka Consumer API 为你提供了位移提交的方法,如 consumer.commitSync 等。当调用这些方法时,Kafka 会向位移主题写入相应的消息。它是一个同步操作,即该方法会一直等待,直到位移被成功提交才会返回。