目录
概述
最近很多同学去面试,都被问到“MQ如何保证消费顺序性”这样一个问题
很多人都没回到上来,特别是面试官在面试的时候,还会再补充一句:“还有没有其他方案”。
然后求职者一脸懵逼,实在不知道该怎么回答。
问题解答
从两个方面来回答:
1、kafka为什么会存在无序消费
2、kafka如何保证有序消费
首先,在kafka的架构里面,用到了Partition分区机制来实现消息的物理存储(如图),在同一个topic下面,可以维护多个partition来实现消息的分片。
生产者在发送消息的时候,会根据消息的key进行取模(如图),来决定把当前消息存储到哪个partition里面。
并且消息是按照先后顺序有序存储到partition里面的。
在这种情况下,(如图),假设有一个topic存在三个partition,而消息正好被路由到三个独立的partition里面。
然后消费端有三个消费者通过balance机制分别指派了对应消费分区。因为消费者是完全独立的网络节点,所有可能会出现,消息的消费顺序不是按照发送顺序来实现的,从而导致乱序的问题。
针对这个问题,一般的解决办法就是自定义消息分区路由的算法,然后把指定的key都发送到同一个Partition里面。(如图)
接着指定一个消费者专门来消费某个分区的数据,这样就能保证消息的顺序消费了。
另外,有些设计方案里面,在消费端会采用异步线程的方式来消费数据来提高消息的处理效率,那这种情况下,因为每个线程的消息处理效率是不同的,所以即便是采用单个分区的存储和消费也可能会出现无序问题,针对这个问题的解决办法就是在消费者这边使用一个阻塞队列,把获取到的消息先保存到阻塞队列里面,然后异步线程从阻塞队列里面去获取消息来消费。
面试点评
关于这个问题,有些面试官还会这样问:如果我不想把消息路由到同一个分区,但是还想实现消息的顺序消费,怎么办?
严格来说,kafka只能保证同一个分区内的消息存储的有序性。
如果一定要去实现,也不是不行,只是代价太大了没必要。
虽然没有标准答案,但是面试官要这么问,无非就是想考察你面对复杂问题的时候是如何思考的,以及你的技术底蕴怎么样。