什么是消息队列
-
- [什么是消息队列 (Message Queue)?](#什么是消息队列 (Message Queue)?)
- 为什么要用MQ?
- 系统架构类比-电商快递分拣中心
-
- [生产者 (Producer) -> 发货商家](#生产者 (Producer) -> 发货商家)
- [消息队列 (Queue) -> 分拣中心的传送带/货架](#消息队列 (Queue) -> 分拣中心的传送带/货架)
- [消费者 (Consumer) -> 快递小哥/货车](#消费者 (Consumer) -> 快递小哥/货车)
- [Topic (主题)-分拣中心有好几条传送带](#Topic (主题)-分拣中心有好几条传送带)
- [Consumer Group (消费者组)](#Consumer Group (消费者组))
- MQ产品对比
- [引入 MQ 带来的挑战 (副作用)](#引入 MQ 带来的挑战 (副作用))
- 结尾
什么是消息队列 (Message Queue)?
简单来说,消息队列是指在应用程序之间传输数据的一种通信方法。
- 消息 (Message):数据本身(可以是简单的文本字符串,也可以是复杂的 JSON 对象)。
- 队列 (Queue):数据存放的容器,遵循"先进先出" (FIFO) 或特定排序规则的管道。
在很多架构中,MQ 扮演着中间件 (Middleware) 的角色。它像一个可靠的中转站,允许系统 A 把数据放进去,然后继续干别的事,而系统可以在稍后的任意时间把数据取出来处理。
为什么要用MQ?
主要是"解耦、异步、削峰"。应该都用过购物app,我们用电商的业务场景很好解释.
解耦 (Decoupling)
假设你有一个"订单系统"。用户下单后,需要调用"库存系统"减库存,"支付系统"扣款,"物流系统"发货。如果直接代码调用(RPC/HTTP),一旦"物流系统"挂了,整个下单流程就会报错,用户体验极差。且每新增一个下游业务(比如加积分),都要修改订单系统的代码。
MQ 方案:订单系统下单成功后,只发一条消息到 MQ。库存、支付、物流系统订阅这个 MQ,自己去消费消息。
结果:订单系统不依赖下游系统的状态。谁想处理订单数据,谁就去订阅,订单系统无需改代码。
异步 (Asynchronous)
用户注册账号,需要写入数据库(50ms)、发注册邮件(100ms)、发短信验证码(100ms)。同步执行总耗时 = 250ms。如果网络抖动,耗时更长,用户会觉得网页"卡住"了。
MQ 方案:将数据写入数据库后(50ms),直接发个消息给 MQ(5ms),然后立刻返回"注册成功"给用户。邮件服务和短信服务在后台慢慢从 MQ 拉取消息去发送。
结果:响应时间从 250ms 降至 55ms,用户体验极大提升。
削峰填谷 (Peak Shaving)
秒杀活动,平时每秒 50 个请求,秒杀开始瞬间飙升到 5000 个请求。由于数据库(MySQL)每秒只能抗 2000 个并发,数据库会瞬间宕机,整个系统瘫痪。
MQ 方案:所有请求先进 MQ。MQ 抗压能力极强(比如 Kafka 每秒百万级吞吐)。后端的业务系统按照自己的处理能力(比如每秒处理 1000 个),匀速地从 MQ 里拉取请求处理。
结果:MQ 就像一个蓄水池,拦住了洪水,保护了下游脆弱的数据库。
系统架构类比-电商快递分拣中心
在这个场景里,我们有三个核心角色:生产者、消费者、MQ。
生产者 (Producer) -> 发货商家
商家打包好一个个包裹(Message 消息),贴上单子。
商家不管谁来送,也不管车有没有来,他唯一的动作就是把包裹扔到分拣中心的传送带上。
消息队列 (Queue) -> 分拣中心的传送带/货架
这是暂存包裹的地方,包裹在这里排队,通常是先进先出(先扔上来的包裹先被运走)。
而且传送带很长,能放很多包裹(堆积能力)。
消费者 (Consumer) -> 快递小哥/货车
快递小哥把车停在传送带尽头,一件件拿包裹装车,然后运走处理。
你也能看到我们这个是kafka专辑,这里有个kafka的特性
Topic (主题)-分拣中心有好几条传送带
传送带 A:专门放去"北京"的包裹。
传送带 B:专门放去"上海"的包裹。
商家发货时,会把包裹扔到指定的传送带上。
Consumer Group (消费者组)
传送带 A 的包裹太多了,一个小哥搬不完,于是叫来了一个车队(消费者组),比如 3 个快递员一起站在传送带 A 的尽头,大家分工合作,你搬第一个,我搬第二个。
这是 Kafka 高吞吐的核心原因:允许多个消费者同时处理一个队列的消息。
MQ产品对比
| 特性 | RabbitMQ | Kafka(本专辑主角) | RocketMQ |
|---|---|---|---|
| 开发语言 | Erlang | Scala / Java | Java |
| 单机吞吐量 | 万级 | 百万级(极高) | 十万级 |
| 时效性 | 微秒级 | 毫秒级 | 毫秒级 |
| 可用性 | 高(主从架构) | 非常高(分布式架构) | 非常高 |
| 核心优势 | 消息传递可靠性极强,支持复杂路由 | 吞吐量巨大,适合大数据日志采集、流计算 | 阿里出品,适合复杂的电商业务逻辑 |
| 典型场景 | 订单处理、一般业务解耦 | 日志分析、大数据流处理、用户行为追踪 | 电商交易、金融级消息 |
引入 MQ 带来的挑战 (副作用)
你我都应该明白一点:技术没有银弹。
必须清楚引入 MQ 后的代价!!!
系统可用性降低
以前是 A 调 B,现在是 A 调 MQ 调 B。如果 MQ 挂了,整个链路都断了。因此,MQ 的高可用 (HA) 是运维和开发的重中之重(Kafka 在这方面做得很好)。
系统复杂度提高
**消息重复消费:**如果消费者处理完业务,但网络抖动没告诉 MQ "我处理完了",MQ 会重发消息。你的业务逻辑必须保证幂等性。
**消息丢失:**数据在传输过程中丢了怎么办?
**消息顺序性:**先下单后支付,如果顺序乱了怎么办?
一致性问题
A 系统处理完了,B 系统消费失败了,导致数据不一致(分布式事务问题)。
结尾
这篇文章大致属于扫盲,是很基础很基础的内容,后续我们会深入的聊一些kafka的内容.
实际上工作一般只要能使用MQ优化架构就完全够用了,就算是面试对于这部分的要求也不会特别高,因为它的结构真的太简单清晰了,就算解决传递消息的问题.
一般在生产环境很少出问题,即使出问题一般也是去找运维处理 😃