如果不学会直面悲哀,就会像深吸了一口气,而后用余生来憋着那口气。
问:如何保障音讯的程序性?
面试官心理剖析
其实这个也是用 MQ 的时候必问的话题,第一看看你了不理解程序这个事儿?第二看看你有没有方法保障音讯是有程序的?这是生产零碎中常见的问题。
面试题分析
我举个例子,咱们以前做过一个 mysql binlog
同步的零碎,压力还是十分大的,日同步数据要达到上亿,就是说数据从一个 mysql 库一成不变地同步到另一个 mysql 库外面去(mysql -> mysql)。常见的一点在于说比方大数据 team,就须要同步一个 mysql 库过去,对公司的业务零碎的数据做各种简单的操作。
你在 mysql 里增删改一条数据,对应进去了增删改 3 条 binlog
日志,接着这三条 binlog
发送到 MQ 外面,再生产进去顺次执行,起码得保障人家是依照程序来的吧?不然原本是:减少、批改、删除;你楞是换了程序给执行成删除、批改、减少,不全错了么。
原本这个数据同步过去,应该最初这个数据被删除了;后果你搞错了这个程序,最初这个数据保留下来了,数据同步就出错了。
先看看程序会错乱的俩场景:
- RabbitMQ:一个 queue,多个 consumer。比方,生产者向 RabbitMQ 里发送了三条数据,程序顺次是 data1/data2/data3,压入的是 RabbitMQ 的一个内存队列。有三个消费者别离从 MQ 中生产这三条数据中的一条,后果消费者 2 先执行完操作,把 data2 存入数据库,而后是 data1/data3。这不显著乱了。
**
Kafka**:比如说咱们建了一个 topic,有三个 partition。生产者在写的时候,其实能够指定一个 key,比如说咱们指定了某个订单 id 作为 key,那么这个订单相干的数据,肯定会被散发到同一个 partition 中去,而且这个 partition 中的数据肯定是有程序的。
消费者从 partition 中取出来数据的时候,也肯定是有程序的。到这里,程序还是 ok 的,没有错乱。接着,咱们在消费者里可能会搞 多个线程来并发解决音讯。因为如果消费者是单线程生产解决,而解决比拟耗时的话,比方解决一条音讯耗时几十 ms,那么 1 秒钟只能解决几十条音讯,这吞吐量太低了。而多个线程并发跑的话,程序可能就乱掉了。
解决方案
RabbitMQ
拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,的确是麻烦点;或者就一个 queue 然而对应一个 consumer,而后这个 consumer 外部用内存队列做排队,而后分发给底层不同的 worker 来解决。
Kafka
- 一个 topic,一个 partition,一个 consumer,外部单线程生产,单线程吞吐量太低,个别不会用这个。
- 写 N 个内存 queue,具备雷同 key 的数据都到同一个内存 queue;而后对于 N 个线程,每个线程别离生产一个内存 queue 即可,这样就能保障程序性。