《漫谈 MQ》要消息队列(MQ)有什么用?
大家好,我是煎鱼。想是问题,做是答案。
最近我有一个朋友公司踩了不少消息队列(MQ)的坑,让人无奈不已。因此计划写 MQ 系列的技术文章,来科普更多这块的知识。
目前 MQ 也是互联网应用中非常常用的基础组件了,面试特爱问。基本有一定规模的系统都能看见他的踪影。
无论是 RocketMQ、Kafka、RabbitMQ 等,都围绕着根本的设计出发产生不同的高级功能,甚至可能是雷同的设计有 N 个名字。
什么是 MQ
MQ 一般代指消息队列(Message Queue)。它是一个抽象层,允许多个进程(可能在不同的机器上)通过各种模式(例如:点对点,发布订阅等)进行通信。
也可以根据不同的实现,它可以被配置为保证可靠性、错误报告、安全、发现、性能等。
为什么需要 MQ
在当下 MQ 的必要场景,比较经典的说辞就是 “异步、削峰、解耦”。是各类秒杀系统的设计核心,甚至会作为不少云厂商的卖点,每家都有自己的生态圈。
核心分为三个要点:
- 解耦。
- 削峰。
- 异步。
解耦
在业务系统设计中,我们常常会与一个平台系统 A,他汇聚了许许多多的系统的对接。例如,系统 A 作为平台拥有大量用户操作,自然就有非常多的用户行为。
虽然他自己可能不大需要,但是其他子系统就不同了,会要系统 A 来调用他们提供的接口,传输各种行为数据。
其链路依赖如下图:
这时候作为平台方的系统 A 就烦死了,来一个要对接一个,就得安排一个人排工期和迭代。对方还有可能出现系统不稳定,还得关注他们的稳定性和诉求。
但用了 MQ 后就不一样了,如下图:
系统 A 只需要将消息放到 MQ 中去,不管以后是对接系统 B、C、D、E…,他都不需要太关心,不用一个个对接。用业务同学的话来讲,就是:“自己看文档,去 MQ 里拿,别来骚扰我”。
以此 MQ 达到了系统间解耦的目的。
削峰
在 2C 类别的业务系统中,常常会有活动的概念,要面向用户做促销,像我们常见的双 11、618 都是这类营销,也是营销场景。
但这种场景之下,会对系统产生较大的冲击。类似八二原则,也就是 80% 的流量集中在某个时间冲击进来,形成了流量尖峰(高 QPS),系统会因为承受不了如此大的压力,从而宕机。
如下图:
用户的请求会经由系统 A 直击数据库。当然,在活动场景下的大流量,数据库自然也就撑不住了。
我们可以利用 MQ 做削峰,系统 A 直接把消息写入 MQ,再让系统 B、C、D 自己主动地根据自身情况来 MQ 拉取消息,又或是接受消息的推送:
这样一来,MQ 作为一个 “转发器”,流量不会直接打到底层,也保证了各业务系统可根据自己的实际负载来决定消费消息的速度,起到流量削峰放缓的作用。
异步
在没有引入 MQ 组件的时候,我们系统 A 因业务需求要调好几个接口时,都可能需要专门的写个异步操作,否则就会导致阻塞等待响应过久。
但是使用 MQ 后,系统只需要快速地将消息写入 MQ 中,接着就可以返回了:
也就是真正的业务操作,被异步化了。“内部” 的区域是业务系统自身需要关注的,而经由 MQ 的 “外部” 操作与系统 A 无关,自然异步处理也问题不大。
MQ 三要素
MQ 一共有三个基本角色,分别是:
- 生产者(Producer):负责生产消息。
- 消费者(Consumer):负责消费消息。
- 队列(Queue):负责存储消息。
这么一看,MQ 就是一个很基础的东西,基本就是一发一存一消费的模型:
-
在 MQ 中传来传去的内容:就是 “消息”,消息是我们业务要传输的数据内容。内容格式为自定义,只要两边商议清楚能解析出来即可。比较常见是像是:JSON、Protobuf 等。
-
消息在 MQ 的队列组件:承载着传输消息的作用,队列是先进先出的数据结构,生产者的消息入队就是发消息,消费者消费消息,也就是队列出队。
消息模型
随着消息的不断规模使用和应用,目前业内常见的有两种模型:
- 点对点模型。
- 发布/订阅模型。
点对点模型
点对点是 MQ 最初的结构,也就是 “生产者-队列-消费者” 的模型:
生产者将消息写入队列,消费者再从队列中读取出消息出来,完成一个标准动作。
当然,在真实环境中,是允许有多个生产者和多个消费者的,也可以根据不同的业务诉求做队列的隔离。
发布/订阅模型
发布/订阅是 MQ 逐渐延伸出来的诉求,因为在实际业务场景中,我们需要将一份消息分发给多个消费者。
多个消费者都要针对这份数据做一些自己的业务处理,那么点对点的就不合适了,除非点对点的开通 N 个队列,但消息的体量可也不少,也不高效,这显然很浪费。
从业务场景来讲,就像平时系统 A 有一份用户行为数据,下游有 N 个系统需要,那咋办。最适合的就是 “发布者-Topic-订阅者” 的模型:
在该模型中,“生产者” 变成 “发布者”,“消费者” 变成了 “订阅者”,以往的 “队列” 也改变了他单一的属性,拆成了更多的组件。一般就是 “主题” 了,也就是 Topic 来做消息存储等。
订阅者只需要订阅 Topic,就可以收到发布者每次发布的这个 Topic 的全量消息,以此达到诉求。
总结
在今天这篇文章中,我们介绍了消息队列(MQ)的相关核心内容:
- MQ 基本介绍和说明。
- MQ 常见的三要素和三大特性进行了分析说明
- MQ 常见的 “点对点” 和 “发布/订阅” 模型。
MQ 总是有利有弊的,在初步了解后,接下来的文章我们将会持续剖析,欢迎关注煎鱼,继续学习 :)