kafka的提交分2种:自动提交和手动提交。
首先提一下消费进度:
每个consumer消费的时候会把进度记录在__consumer_offsets开头的目录中(本质就是一个topic),这样即使consumer宕机了,重启后也不至于从头开始消费。
这个消费进度信息在老版本是由zookeeper管理,在新版本存由kafka管理。放在zookeeper的问题很明显,zookeeper是面向整个系统的协调服务,侧重于数据一致性,每次更改都会开启事务同步各个子节点。流处理业务提交频繁,zookeeper会负载过高,影响到整个系统的性能。
题外:关于消费进度还有一点,跟commit无关,就是在流处理程序中可能会执行多次poll,过程中并没有commit,但是仍然可以正常拉取,不会重复拉取消息。这是因为consumer在内存中存了一份“fetch offset”。
自动提交流程:
在流处理过程中,consumer会间隔时间从partation上poll一部分数据,然后就是进行业务处
理。每次poll数据的时候会把前一次poll的消费进度提交。
提交的时间点是固定的下一次poll的时候。
可能遇到的问题:
业务正常处理完成并且入库了,但是随后consumer宕机了,导致这次poll的进度并没有落盘。重启后出现重复消费问题。
实际流处理程序中我们还可能自己设计一个缓存,每积累一定量再业务处理,这种流程中可能会出现缓存没积累够之前就poll过了至少一次,即已经提交了消费进度。这时候如果consumer宕机,则消费数据没来得及处理入库,出现丢数据问题。
手动提交流程:
手动提交通常只会在业务处理之后提交消费进度。
可能遇到的问题:
手动提交消费进度之前,如果业务正常处理并入库,随后宕机。导致重复消费问题。
总结:
不管自动提交还是手动提交,遇到的问题本质都是数据一致性的问题,可以理解为业务处理数据并入库的进度和kafka的消费进度出现不一致。
终极方案:
如果对数据一致性要求非常苛刻,可以考虑把消费进度存在业务数据库中,消费进度和业务处理统一管理,并且能保证一致。
网友评论