阿里面试:canal+MQ,会有乱序的问题吗?
尼恩说在前面
在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:
canal+MQ,会有乱序的问题吗?
如何保证RocketMQ消息有序?
最近有小伙伴在面试阿里,又遇到了相关的面试题。
小伙伴懵了,因为没有遇到过,所以支支吾吾的说了几句,面试官不满意,面试挂了。
所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。
当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V140版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到文末公号【技术自由圈】获取
1、如何保证消息顺序?
如何实现消息有序?实现顺序消息所必要的条件:顺序发送、顺序存储、顺序消费。
在MQ模型中,顺序需由3个阶段去保障
- 顺序发送: 发送时保持顺序一致
- 顺序存储: broker 存储时保持 顺序一致
- 顺序消费: 消费时 保持 顺序一致
2 消息有序的两大类型
有序消息,又叫顺序消息(FIFO消息),指消息的消费顺序和产生顺序相同。
如订单的生成、付款、发货,这串消息必须按序处理。
顺序消息又可分为全局有序和局部有序:
- 全局有序:整个MQ系统的所有消息严格按照队列先入先出顺序进行消费
- 局部有序:只保证一部分关键信息的消费顺序
2.1 全局顺序
一个Topic内所有的消息都发布到同一Q,按FIFO顺序进行发布和消费:
落地到RocketMQ,如何保证全局有序?
为了 保证Topic全局消息有序的方式,就是将Topic配置成只有一个唯一的MessageQueue队列, 默认是4个MessageQueue。
RocketMQ中,可以在发送者发送消息时指定一个MessageSelector对象,让这个对象来决定消息发入哪一个MessageQueue。这样就可以保证一组有序的消息能够发到同一个MessageQueue里。
适用场景
性能要求不高,所有消息严格按照FIFO进行消息发布和消费的场景。
2.2 分区顺序
对于指定的一个Topic,所有消息按sharding key
进行区块(queue)分区,同一Queue内的消息严格按FIFO发布和消费。
- Sharding key是顺序消息中用来区分不同分区的关键字段,和普通消息的Key完全不同。
落地到RocketMQ。而MessageQueue是RocketMQ存储消息的最小单元,他们之间的消息都是互相隔离的,在这种情况下,是无法保证消息全局有序的,但是可以保证局部有序。
默认的做法是,发送消息时,会通过MessageQueue轮询的方式保证消息尽量均匀分布到所有的MessageQueue上,而消费者也就同样需要从多个MessageQueue上消费消息。这就做不到局部有序。
对于局部有序的要求,只需要将有序的一组消息都存入同一个MessageQueue里,这样MessageQueue的FIFO设计天生就可以保证这一组消息的有序。
适用场景
性能要求高,根据消息中的sharding key去决定消息发送到哪个queue。
其实大部分的MQ业务场景,我们只需要保证局部有序就可以了。
例如
我们用QQ聊天,只需要保证一个聊天窗口里的消息有序就可以了。
而对于电商订单场景,也只要保证一个订单的所有消息是有序的就可以了。
2.3 对比
发送方式对比
存储方式对比
- 无
消费方式对比
有序消费的消费者类型:ConsumeMessageConcurrentlyService 并发消费服务
无序消费的消费者类型:ConsumeMessageOrderlyService
3 应用开发维度的实现消息有序需要做的工作:
实现顺序消息所必要的条件:顺序发送、顺序存储、顺序消费。 顺序存储环节,RocketMQ 里的分区队列 MessageQueue 本身是能保证 FIFO 的。
所以,在应用开发过程中,不能顺序消费消息主要有两个原因:
- 顺序发送环节,消息发生没有序:Producer 发送消息到 MessageQueue 时是轮询发送的,消息被发送到不同的分区队列,就不能保证 FIFO 了。
- 顺序消费环节,消息消费无序:Consumer 默认是多线程并发消费同一个 MessageQueue 的,即使消息是顺序到达的,也不能保证消息顺序消费。
我们知道了实现顺序消息所必要的条件:顺序发送、顺序存储、顺序消费。
顺序存储 由 Rocketmq 完成,所以,在应用开发层, 消息的顺序需要由两个阶段保证:
- 消息发送有序
- 消息消费有序
4:canal+MQ,如何实现有序?
Canal 是阿里巴巴开源的一个增量订阅和消费的中间件,用于基于 MySQL 的数据库增量日志解析(Binlog)。通过 Canal,可以实现对数据库的实时监控和数据同步。
我们在通过Canal把MySQL的Binlog数据发送到MQ(kafak/rocketmq)时,需要关注好几个环节:
- Cannal 的有序监听。 Binlog本身是有序的,写入到mq之后如何保障顺序
- Cannal 的有序发送。
- 顺序存储: broker 存储时保持 顺序一致
- 顺序消费: 消费时 保持 顺序一致
4.1 Cannal 的有序发送
canal目前支持kafka和rocketmq,在使用 Canal 进行数据同步时,保证数据的有序性是一个重要的问题,尤其是在分布式环境中。在 Kafka 或 RocketMQ 等消息队列中,消息的顺序性和分区策略至关重要。
canal 本质上都是基于本地文件的方式来支持分区级别的顺序消息,也就是binlog写入mq是可以有一定的顺序性保障,这个保障级别取决于用户的两个配置项:
canal.mq.partitionsNum
canal.mq.partitionHash
两个配置项 用于控制消息的分区和顺序。两个配置项介绍如下:
- canal.mq.partitionsNum:
- 描述:设置消息队列的分区数量。
- 作用:决定了消息在消息队列中被分区的数量。不同的分区可以并行处理,但需要注意同一个分区内的消息是有序的。
- canal.mq.partitionHash:
- 描述:设置消息分区的哈希规则。
- 作用:用于指定分区的哈希策略,可以根据特定的字段进行分区。例如,可以根据表名、主键等字段进行分区,以保证某些关键数据的有序性。
4.2 Cannal 的有序发送示例
假设我们希望将数据同步到 Kafka,并且需要保证某张表的数据是有序的,可以使用以下配置:
canal.mq.partitionsNum=10
canal.mq.partitionHash=my_database.my_table:id
配置解释
- canal.mq.partitionsNum=10:
- 表示消息会被分成 10 个分区。每个分区可以并行处理,从而提高处理效率。
- canal.mq.partitionHash=my_database.my_table
- 针对
my_database.my_table
表的数据,根据id
字段进行哈希分区。 - 这样可以确保同一个
id
的所有变更都进入同一个分区,从而保证该id
的变更顺序不变。
- 针对
通过配置 canal.mq.partitionHash
,分区内的消息是有序的,因此只要保证同一实体(如同一行数据)的变更进入同一个分区,就能保证其有序性。
4.3 Cannal 的使用场景
- 实时数据同步:将数据库的变更实时同步到其他系统,如搜索引擎、缓存等。
- 数据备份:实现数据库的实时备份,确保数据的一致性和完整性。
- 事件驱动架构:在事件驱动架构中,利用 Canal 将数据库变更作为事件发布到消息队列,供其他系统消费。
通过合理配置 canal.mq.partitionsNum
和 canal.mq.partitionHash
,可以在数据同步中既保证有序性,又提高处理效率。
尼恩《技术自由圈》多个核心MQ面试题
惊呆:RocketMQ顺序消息,是“4把锁”实现的(顺序消费)
阿里面试:如何保证RocketMQ消息有序?如何解决RocketMQ消息积压?
说在最后
至此,Canal+MQ的有序性方案,非常圆满了。
以上的内容,如果大家能烂熟于心、对答如流、如数家珍,基本上 面试官会被你 震惊到、吸引到。
最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。
在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。很多小伙伴刷完后, 吊打面试官, 大厂横着走。
在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。
另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。
遇到职业难题,找老架构取经, 可以省去太多的折腾,省去太多的弯路。
尼恩指导了大量的小伙伴上岸,前段时间,刚指导一个40岁+被裁小伙伴,拿到了一个年薪100W的offer。
尼恩技术圣经系列PDF
- 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
- 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
- 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
- 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
- 《大数据HBase学习圣经:一本书实现HBase学习自由》
- 《大数据Flink学习圣经:一本书实现大数据Flink自由》
- 《响应式圣经:10W字,实现Spring响应式编程自由》
- 《Go学习圣经:Go语言实现高并发CRUD业务开发》
……完整版尼恩技术圣经PDF集群,请找尼恩领取
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓