Q1: Kafka 消费者是如何消费Topic 中的数据的?
任何一个消费者消费Topic中的数据,分为两种情况:
- 第一次消费
任何一个消费者必须以消费者组的形式去消费数据。如果消费者组在Kafka中的元数据不存在,即为第一次消费。此时的消费规则是由下面的属性决定:
auto.offset.reset = last | earliest;
(1)默认该属性为last,即为从最新的位置开始消费;而当我们把该属性的值改为earliest,则消费者会从头开始消费。
(2)上面的属性的值的设置只有在消费者组第一次消费数据才会生效。但凡有消费过,上面的属性就不生效了。
- 非第一次消费
即消费者组的id已经在Kafka的元数据中登记过了。此时的消费规则是:
根据上一次消费的每个分区的offset位置(consumer offset) + 1 ,即commit offset的位置继续进行消费。
(1)consumer offset:消费者已经消费到这个分区的offset
(2)commit offset:消费者下一个要消费的offset
关系:commit offset = consumer offset + 1;
Q2: Kafka 消费者如何知道下一次请求的位置是什么?
答:每个消费者会维护自己下一次要消费的commmit offset,并把它放在自己的内存中。
Q3: 如果消费者故障重启,消费者怎么知道自己上次消费的位置的?又或者如果这个消费者长时间没有重启,这个分区会交给这个消费者组中的其他消费者消费,其他消费者怎么知道这个分区下一次消费的位置是什么呢?
原因:每个分区下一次要消费的offset放在消费者客户端的内存中,一旦消费故障,内存数据会丢失,offset 就丢失了。
解决:将offset 持久化存储,不仅仅放在内存中,如果内存丢失,其他的地方能读到。这个地方一定是一个公共的,高可靠的存储系统。
这里,有必要了解 Kafka offset 偏移量的管理。具体看下面的解析。
Q4: Kafka offset 偏移量的管理
Kafka默认方案:Kafka 让所有的消费者每个分区下次消费的位置主动记录在一个Topic中,这个Topic的名字是:__consumer_offset。每个负责消费这个分区的消费者会主动将自己消费的commit offset 写入该Topic中。
可选方案:自己管理offset,基于自己消费情况,消费成功以后,将每个分区的offset记录在可靠存储。如:MySQL、Zookeeper、Redis、共享文件【Flink/Spark: checkpoint】
示例伪代码:
step1: 消费拉取数据
offset = OffsetUtils.readOffset(groupid,topic,partiton)
consumer.seek(partition,offset)
step2: 处理数据
step3: 保存offset
OffsetUitls.writeToMySQL(groupid,topic,partition,offset+1): replace
网友评论