前言
由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置的继续消费,所以consumer需要实时记录自己消费到了哪个offset,以便故障恢复后继续消费。
这个offset的信息是在哪?怎么维护的?
概述
Kafka 0.9版本之前,consumer默认将offset保存在Zookeeper中,从0.9版本开始,consumer默认将offset保存在Kafka一个内置的topic中,该topic为__consumer_offsets。
老版本的时候这些消息是ZK存的,新版本Kafka自己记录了,消费者消费到哪里
磁盘上查看
Kafka中查看该主题

Kafka一个内置的topic中,该topic为__consumer_offsets。无法精确记录消费到哪个位置,每一秒记录一次offset位置,无法精确记录位置,不能精确消费,想要精确消费,消费者自己记录offset位置。
Consumer消费数据时的可靠性是很容易保证的,因为数据在Kafka中是持久化的,故不用担心数据丢失问题。
由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置的继续消费,所以consumer需要实时记录自己消费到了哪个offset,以便故障恢复后继续消费。所以offset的维护是Consumer消费数据是必须考虑的问题。
自动提交offset
自动提交就是offset由broker来进行保存,会有一定的问题
Broker在设定的时间范围内记录offset,比如一秒记录一次
Consumer拉了500条数据,1秒钟,消费者只存了300条,因为是自动提交,所以1秒钟情况下,broker记录消费的offset位置为500
如果此时consumer突然挂了,重启再拉数据就从500开始拉了,这就有问题了呀,差了200条
手动提交offset
手动提交offset的方法有两种:分别是commitSync(同步提交)和commitAsync(异步提交)。两者的相同点是,都会将本次poll的一批数据最高的偏移量提交;不同点是,commitSync阻塞当前线程,一直到提交成功,并且会自动失败重试(由不可控因素导致,也会出现提交失败);而commitAsync则没有失败重试机制,故有可能提交失败。
无论是同步提交还是异步提交offset,都有可能会造成数据的漏消费或者重复消费。先提交offset后消费,有可能造成数据的漏消费;而先消费后提交offset,有可能会造成数据的重复消费。
手动提交,不管是同步还是异步,都会有重复消费的问题,比如消费者拉取了500条,消费了300条,在提交offset前消费者挂了,提交offset的操作都没有做,没提交上,重启后再拉数据还是从原先的位置拉取的
Consumer事务
目的是:保证精确消费一次
对于Consumer而言,事务的保证就会相对较弱,尤其时无法保证Commit的信息被精确消费。这是由于Consumer可以通过offset访问任意信息,而且不同的Segment File生命周期不同,同一事务的消息可能会出现重启后被删除的情况。
如果想完成Consumer端的精准一次性消费,那么需要kafka消费端将消费过程和提交offset过程做原子绑定。此时我们需要将kafka的offset保存到支持事务的自定义介质中(比如mysql)。
