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会丢失