弄浪的鱼

消息队列思维导图

1. 引子

消息队列分布式系统中重要的组件,一种存放消息的容器,主要作用有解耦、异步、削锋,是大型分布式系统不可缺少的中间件。

常见的消息队列有 ActiveMQ,RabbitMQ,RocketMQ,Kafka。

简历中涉及到了消息队列,面试官先问了这样几个问题:

  1. 你们系统里为什么要使用消息队列?
  2. 既然使用了消息队列,说说他还有什么使用场景?
  3. 消息队列的优缺点是什么?

2. 为什么使用消息队列?

我的回答:甲方提供 EOS 充值服务,我方进行调用。出于解耦的目的,引入了消息队列。

一个类似应试的回答方法,就是思考面试官问这个问题是出于什么目的,想获得的是什么样的答案?

当问到为什么使用消息队列时,面试官期望的回答是公司的 xxx 业务遇到了挑战,不用 MQ 会有麻烦,使用 MQ 之后带来了好处。

通过一个问题就能看出是为了用而用,还是经过思考之后使用。

3. 消息队列的使用场景?

问消息队列的使用场景,和问消息队列有什么优点,消息队列有什么作用是等价的。

消息队列的作用主要有三个解耦、异步、削峰

解耦

解耦

B,C,D 系统需要使用 A 系统产生的关键数据。

  • 无消息队列时
    • 系统 A 为系统 B、C、D 等提供各自的接口,导致系统 A 与它们紧密耦合
    • 添加系统 E 又需要接口,删除 B 系统原接口又没用了
  • 有消息队列时
    • 系统 A 作为生产者,将消息发送到消息队列
    • 系统 B、C、D 作为消费者订阅消息
    • 新增消费者只需订阅消息,对原系统和业务没有影响

异步

异步.png

用户请求数据时,系统的响应时间是保证用户体验很重要的一部分。

  • 无消息队列时
    • 用户请求 A 系统,A 系统需要等待 BCD 执行完成之后响应
    • 用户收到响应用时近 1 秒
  • 用消息队列时
    • 用户请求 A 系统,A 系统将请求推到消息队列中,B、C、D 异步执行
    • 用户收到响应用时 200 毫秒

削峰

削峰.png

秒杀场景下,每秒有 5000 个请求,Mysql 每秒最大处理 2000 条 sql。

  • 无消息队列时
    • 用户请求数据直接写入数据库,高并发时数据库压力剧增,甚至奔溃
    • Mysql 宕机,整个系统都不能用了
  • 有消息队列时系统 B、C、D
    • 用户请求数据先存入 MQ 中
    • 系统 A 每秒读取 2000 条数据进行处理
    • 每秒多出 3000 条未处理数据按场景稍后处理

4. 消息队列有什么缺点?

优点前面已经说过了,还需要讨论一下缺点。

为什么要问缺点是什么?

凡事都有两面性,如果只是考虑到消息队列的优点,而没有考虑缺点,这就是一个潘多拉的魔盒。打开魔盒,接踵而来的会是一系列的意外。

推广到引入其他技术亦然,只有考虑到缺点之后才可以采取额外的技术方案或者架构来规避这些缺点。

系统可用性降低

  • 系统引入的外部依赖越多,宕机的可能性就越大
  • 系统引入消息队列,就要考虑消息队列的可靠性
  • 比如原本只需要考虑 A,B,C,D 四个系统
  • 引入消息队列之后就需要考虑 A,B,C,D 四个系统外加消息队列

系统复杂度提高

  • 消息重复消费问题
  • 消息丢失问题
  • 消息传递顺序问题

一致性问题

  • A 系统处理完返回成功,即认为请求成功
  • 但是也存在 BC 系统写入成功,而 D 系统写入失败的情况
  • 这样的情况就是数据不一致

总结

面试官问到 MQ 的时候,希望考察我们在使用 MQ 的时候是否有过自己的思考。没有完美的技术,任何技术都具有两面性,要考虑它的使用场景,并且对可能遇到的风险做到心中有数,提前预防。

消息队列思维导图

思考

引入消息队列之后:

  • 如何保证高可用?
  • 如何避免消息的重复消费和消息丢失?
  • 如何保证消息的顺序执行?

下一篇文章一起讨论。