面试题如何保证消息的顺序?面试官心理分析其实这也是使用MQ必须要问的话题。首先,看看你是否理解命令?第二,看看你有没有办法保证消息是有序的?这是生产系统中的常见问题。面试题解析我举个例子。之前搭建过mysql的binlog同步系统,压力还是很大的。每天的同步数据要达到上亿,也就是说数据是原封不动的从一个mysql数据库同步到另一个mysql数据库。进入内部(mysql->mysql)。一个共同点是,比如一个大数据团队需要同步一个mysql库,对公司业务系统的数据进行各种复杂的操作。你在mysql中增删改一条数据,对应3个binlog日志的增删改查,然后将这3个binlog发送到MQ,然后依次消费和执行。至少你得保证人是按顺序来的,对吧?否则,原来是:增、改、删;你只是改变了执行删除、修改和添加的顺序,这不都是错误的吗?本来是同步数据的,最后应该是删除了数据;结果你把顺序弄错了,最后还是保留了数据,数据同步就出错了。我们先来看一下会出现顺序乱序的两种场景:RabbitMQ:一个队列,多个消费者。例如生产者向RabbitMQ发送了3条数据,顺序为data1/data2/data3,推入RabbitMQ的一个内存队列中。有3个consumer,分别从MQ中消费这3条数据中的一条。结果消费者2先执行操作,将data2存入数据库,然后是data1/data3。不是很明显乱了Kafka:比如我们建了一个topic,有3个partition。生产者在写的时候,其实可以指定一个key。比如我们指定一个订单id作为key,那么这个订单相关的数据就会分布到同一个分区中,这个分区中的数据一定是有序的。当消费者从分区中获取数据时,它必须是有序的。到此为止,顺序还是ok的,没有出现混乱。那么,我们可能会在consumer中搞多线程并发处理消息。因为如果消费者单线程消费和处理,而且处理很耗时,比如处理一条消息需要几十ms,那么一秒只能处理几十条消息,吞吐量太大低的。如果多个线程并发运行,可能会乱序。解决方案:RabbitMQ拆分了多个队列,每个队列都有一个消费者,就是队列多了,真的很麻烦;或者只有一个queue但是对应一个consumer,然后consumer内部使用内存queues进行排队,然后分发给不同的底层worker去处理。Kafka有一个主题、一个分区和一个消费者。它使用内部单线程消费。单线程吞吐量太低,一般不用。写入N个内存队列,相同key的数据全部进入同一个内存队列;那么对于N个线程,每个线程分别消费一个内存队列,这样就可以保证顺序。《2020最新Java基础精讲视频教程和学习路线!》
