顺序消息
kafka想要保证消息顺序,是需要牺牲一定性能的,方法就是一个消费者,消费一个分区,可以保证消费的顺序性。但也仅限于消费端消费消息的有序性,无法保证生产者发送消息有序。
比如:如果发送端配置了重试机制,kafka不会等之前那条消息完全发送成功才去发送下一条消息,这样可能会出现,发送了1,2,3条消息,第一条超时了,后面两条发送成功,再重试发送第1条消息,这时消息在broker端的顺序就是2,3,1了。发送端消息发送已经乱序,到了消费端消费时,自然无法保证顺序!
如果一定要保证生产-消费全链路消息有序,发送端需要同步发送,ack回调不能设置为0。且只能有一个分区,一个消费者进行消费,但这样明显有悖于kafka的高性能理论!
问题:如何在多个分区中保证消息顺序和消息处理效率呢?
首先使用多个分区,消息可以被发送端发送至多个分区,保证消息发送的效率。然后在消费端在拉消息时使用ConutdownLunch来记录一组有序消息的个数。如果达到个数,说明已拉取到完整的一组有序消息。然后在消费端根据消息序号进行排序,消费端将排好序的消息发到内存队列(可以搞多个),一个内存队列开启一个线程顺序处理消息。即可最大程度上既保证顺序又保证效率!
消息积压
线上有时因为发送方发送消息速度过快,或者消费方处理消息过慢,可能会导致broker积压大量未消费消息。
解决方案:此种情况如果积压了上百万未消费消息需要紧急处理,可以修改消费端程序,让其将收到的消息快速转发到其他topic(可以设置很多分区),然后再启动多个消费者同时消费新主题的不同分区。如图所示:
由于消息数据格式变动或消费者程序有bug,导致消费者一直消费不成功,也可能导致broker积压大量未消费消息。
解决方案:此种情况可以将这些消费不成功的消息转发到其它队列里去(类似死信队列),后面再慢慢分析死信队列里的消息处理问题。这个死信队列,kafka并没有提供,需要整合第三方插件!
消息回溯
如果某段时间对已消费消息计算的结果觉得有问题,可能是由于程序bug导致的计算错误,当程序bug修复后,这时可能需要对之前已消费的消息重新消费,可以指定从多久之前的消息回溯消费,这种可以用consumer的offsetsForTimes、seek等方法指定从某个offset偏移的消息开始消费,完成消息的回溯消费!
kafka高性能的原因
-
分布式存储架构
-
磁盘顺序读写
kafka消息不能修改以及不会从文件中间删除保证了磁盘顺序读,kafka的消息写入文件都是追加在文件末尾,不会写入文件中的某个位置(随机写)保证了磁盘顺序写。 -
读写数据的批量batch处理以及压缩传输
-
数据传输的零拷贝