1 简介
在kafka,生产者生产的消息,只会保证一个生产者生产的消息在一个partion里面是有序的。
所以在编程时,若业务对消息的顺序性有更多的要求,那么就需要自己来保证消息的顺序性了。
消费者消费了消息,offset是需要自己来维护的。也就是说需要自己去保障消费的顺序性。
2 生产者顺序的保证
由于kafka只保证了一个生产者到一个partion中的消息的顺序性,所以需要根据业务需求生成消息时要去控制生产消息的顺序。
2.1 需要保证所有消息有序
可以采用一个生产者,一个topic,同一个key,这样所有消息可以打到同一个partion。
2.2 需要按消息类别保证顺序性
消息可分类好3类业务消息,只需保证每一类业务消息的顺序性。
为了提高效率,那么就可以起三个线程,三个生产者,每个线程生产一类消息,每一类消息的key不同。这样可以保证同一类消息都打到同一个partion,保证每一类消息的顺序性。并且key不同,可以将3类消息均衡到不同的partion。
总之,根据业务的需求,在生成消息时,要考虑消息的顺序性,加以控制
3 消费者顺序的保证
3.1 单线程模式
在这种模式下,可以保证partion里面消息消费的顺序性
3.2 多线程模式
在这种模式下,要保证同一个partion,消息的顺序性,就需要进行一定的处理了
1)按批次提交
一次性拉取一批消息,多个线程处理,(不管消息来自什么分区),全部完成后,统一提交,再维护offset,如果有一个失败,就全部回滚。
优点:能够保证消息的顺序性
缺点:效率低
2)按分区提交
一次性拉取一批消息,多个线程处理,一个线程处理同一个分区的消息,完成后,提交。
优点:分区和分区之间的消息互不影响。一个分区的消息处理失败了,不影响其他分区消息的提交。
在多线程下,上面的两种方式可以保证同一个partion消息的顺序性,且不会丢失消息也不会重复消费。
3.3 允许重复消费
在某些业务场景下,若允许重复消费,那么可以采取下面的方式,最大连续offset维护原则。
一次性拉取一批消息,处理之后,看已完成的消息中,连续的最大的offset是多少,根据这个offset来维护offset
如下图,一次拉取了4条消息,处理后1,2,4成功,3失败,按照2来维护offset,下一次拉取的时候还会从3开始拉取,这样子3不会漏掉,但是4会重复消费。
这样子处理比批处理或分区处理效率更高
3.4 允许丢失消息
在某些业务场景下,若允许丢失消费,那么可以采取下面的方式最大offset维护原则。
一次性拉取一批消息,处理之后,看已完成的消息中,最大的offset是多少,根据这个offset来维护offset
如下图,一次拉取了4条消息,处理后1,2,4成功,3失败,按照4来维护offset,下一次拉取的时候会从5开始拉取
这样子4不会重复消费,但是3会丢失