目录
3、你们公司生产环境用的是什么消息中间件?为什么使用这个MQ?
5、如何保证RabbitMQ消息的可靠性传输?或者消息丢失了怎么办?
9、如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万条消息持续积压几个小时,该怎么去解决?
10、如果让你写一个消息队列,你如何进行架构设计,说一下你的思路?
1、为什么使用MQ?不直接使用接口?===>MQ的优点
异步处理---提高系统吞吐量和降低响应时间
服务解耦---服务间通过消息通信,不需要管别的服务是怎么处理的,易于维护
流量削峰---减少高并发请求对服务器的压力。
消息通讯---可以实现点对点的消息通讯或者群聊
日志处理---解决大量的日志传输
2、使用MQ的缺点?
系统可用性降低---
系统引入的外部依赖越多,越容易挂掉,万一MQ挂掉了,MQ一挂,整套系统都崩了
系统复杂度提高---
硬生生加个MQ进来,如何保证消息的可靠性?如何保证消息不被重复消费?怎么保证消息队列的高可用?等等问题又一大堆。
一致性问题---
A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。
3、你们公司生产环境用的是什么消息中间件?为什么使用这个MQ?
这个首先你可以说下你们公司选用的是什么消息中间件,比如用的是RabbitMQ,然后可以初步给一些你对不同MQ中间件技术的选型分析。
举个例子:比如说ActiveMQ是老牌的消息中间件,国内很多公司过去运用的还是非常广泛的,功能很强大。但是问题在于没法确认ActiveMQ可以支撑互联网公司的高并发、高负载以及高吞吐的复杂场景,在国内互联网公司落地较少。而且使用较多的是一些传统企业,用ActiveMQ做异步调用和系统解耦。
然后你可以说说RabbitMQ,他的好处在于可以支撑高并发、高吞吐、性能很高,同时有非常完善便捷的后台管理界面可以使用。另外,他还支持集群化、高可用部署架构、消息高可靠支持,功能较为完善。而且经过调研,国内各大互联网公司落地大规模RabbitMQ集群支撑自身业务的case较多,国内各种中小型互联网公司使用RabbitMQ的实践也比较多。
除此之外,RabbitMQ的开源社区很活跃,较高频率的迭代版本,来修复发现的bug以及进行各种优化,因此综合考虑过后,公司采取了RabbitMQ。
但是RabbitMQ也有一点缺陷,就是他自身是基于erlang语言开发的,所以导致较为难以分析里面的源码,也较难进行深层次的源码定制和改造,毕竟需要较为扎实的erlang语言功底才可以。
然后可以聊聊RocketMQ,是阿里开源的,经过阿里的生产环境的超高并发、高吞吐的考验,性能卓越,同时还支持分布式事务等特殊场景。
而且RocketMQ是基于Java语言开发的,适合深入阅读源码,有需要可以站在源码层面解决线上生产问题,包括源码的二次开发和改造。
另外就是Kafka。Kafka提供的消息中间件的功能明显较少一些,相对上述几款MQ中间件要少很多。但是Kafka的优势在于专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计。因此Kafka在大数据领域中配合实时计算技术(比如Spark Streaming、Storm、Flink)使用的较多。但是在传统的MQ中间件使用场景中较少采用
4、几种MQ的区别?
对于单继吞吐量来说kafka和RocketMQ支撑高吞吐,ActiveMQ和RabbitMQ比他们低一个数量级。延迟来说RabbitMQ是最低的,而且支持高并发,毕竟它有先天的优势是基于
erlang
语言开发的。
5、如何保证RabbitMQ消息的可靠性传输?或者消息丢失了怎么办?
消息丢失有多种可能情况:消息到MQ的过程中搞丢,MQ自己搞丢,MQ到消费过程中搞丢。
生产者到RabbitMQ
:事务机制(同步处理),缺点是会导致系统吞吐量下降。或开启Confirm机制(异步处理),这是比较推荐的解决方案,Confirm机制是通过Ack和Nack来保证消息正确的传输到MQ队列的。
RabbitMQ自身
:消息持久化、集群、普通模式、镜像模式。
RabbitMQ到消费者
:basicAck机制、死信队列、消息补偿机制。
6、如何保证消息不被重复消费?或如何解决消息的重复问题?
造成消息重复的根本原因是:网络不可达。
所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?
消费端处理消息的业务逻辑需要保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。保证每条消息都有唯一编号和添加一张日志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日志表中,那么就不再处理这条消息。
7、如何保证消息的顺序?或如何解决消息顺序错乱的问题?
保证生产者 - queue - 消费者是一对一对一的关系
RabbitMQ:拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;或者就一个 queue 但是对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。
其他解决方案
方案一:消费端增加消息记录表,暂存不满足业务条件的消息,并采用定时器进行补偿处理,补偿超次进行预警;(该方案对技术营运友好,目前DMS正在使用,同样该方案可以用来解决重复消费问题)
方案二:消费端对不满足业务条件的消息不进行确认,多次消费失败进入死信队列,监听死信队列进行补偿,补偿超次或失败进行预警;
8、你们是怎么保证消息的高可用的?
RabbitMQ 有三种模式:
单机模式
,普通集群模式
,镜像集群模式
。单机模式:就是demo级别的,一般就是你本地启动了玩玩儿的,没人生产用单机模式
普通集群模式:意思就是在多台机器上启动多个RabbitMQ实例,每个机器启动一个。
镜像集群模式:这种模式,才是所谓的RabbitMQ的高可用模式,跟普通集群模式不一样的是,你创建的queue,无论元数据(元数据指RabbitMQ的配置数据)还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。好处在于数据不会容易丢失,坏处在于开销加大了。
9、如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万条消息持续积压几个小时,该怎么去解决?
解决消息堆积有两种思路:
增加更多消费者,提高消费速度。也就是我们之前说的work queue模式
扩大队列容积,提高堆积上限
10、如果让你写一个消息队列,你如何进行架构设计,说一下你的思路?
比如说这个消息队列系统,我们从以下几个角度来考虑一下:
首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量,那怎么搞?设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了?
其次你得考虑一下这个 mq 的数据要不要落地磁盘吧?那肯定要了,落磁盘才能保证别进程挂了数据就丢了。那落磁盘的时候怎么落啊?顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路。
其次你考虑一下你的 mq 的可用性啊?这个事儿,具体参考之前可用性那个环节讲解的 kafka 的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。
能不能支持数据 0 丢失啊?可以的,参考我们之前说的那个 kafka 数据零丢失方案。