如何保证Kafka有序消费
乱序原因
Kafka通过多个Partition来提高吞吐量,多线程并发写入,但这也导致无法保证多个Partition之间的消息有序。Kafka本身设计更适用于不需要严格有序消费的流数据处理。
还可能出现由于重试、网络延迟等问题出现乱序现象。
消费者多线程消费的问题等等
以下 用binlog消费为例
解决方案
对于上述出现乱序的原因,保证有序性消费就需要我们在有效利用MQ本身提供的一定的有效性保证和外部引入顺序校验的处理机制。
方案一
抛弃Kafka提供的高吞吐特性,使用单Partition。
进一步避免多线程导致乱序,还需要配置单线程消费和生产。
对于网络问题可以通过版本校验保证一定的顺序性
binlog校验参考canal的实现,利用binlog中带有的执行时间和position,只有消费的消息都大于消费者保存的最大值,说明不是已经消费过的消息。
优点
简单,只需要改配置
缺点
性能非常低下,可用性和拓展性都无法保证,存粹的简单实践
方案二
利用Producer可以通过key指定发往的Partion
通过将需要有序消费的发往同一个Partition,消费者消费固定的Partition就可以保证有序消费
例如,binlog中相同主键的消息就发往同一个Partition。
对于网络延迟等导致的还是利用校验机制保证
优点
利用Producer提供的特性,既提供有可用性和可拓展性,又保证了一定的有序消费
缺点
对于同一个Partition的消息还是需要同一个线程处理,如果并发处理的话,还是不能保证有序
方案三
在方案二的基础上,将消费者线程获得的消息并发消费,我们可以在线程处理前增加个内存队列,每个线程只负责处理其中一个内存队列的消息,同一个Key的消息发送到同一个内存队列中即可。
发往同一个内存队列可以使用CurrentHashMap
需要注意用于校验的本地变量需要共享和同步机制
如果服务多机部署还需要进一步使用寻找一个中心储存用于处理并发冲突。
优点
进一步将增加消费者处理效率