MQ简介
消息队列(Message Queue,简称 MQ)为分布式应用系统提供异步解耦、削峰填谷的能力,同时具备海量消息堆积、高吞吐、可靠重试等互联网应用所需的特性。用于实现高性能,高可用,可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,RocketMQ。
MQ的核心特性
-
消息堆积能力
- 当突然 流量暴增消息可堆积在MQ当时,MQ起到缓冲作用。
-
消息可靠不丢失
- 生产者、发布者,一旦把消息发给了MQ并收到“已接收确认”,消息就不会丢失,由MQ持久存储保证。
-
可靠重试
- 消费者、订阅者,把消息取走办理业务时异常失败宕机了,MQ未收到“办理成功”的通知,是不会删除消息的。保证消费者、订阅者在恢复后还能再取到这个消息,再办业务。
- 业务本身也需求具有幂等性,来支持可靠重试。
MQ的两种模式
- Producer/Consumer模式,生产者/消费者模式;
- Publish/Subscribe模式,发布/订阅模式;
生产者/消费者模式
Producer/Consumer模式 生产者/消费者模式。
Producer是生产者,负责产生一个消息。并放入Queue。Queue是队列,可按顺序存储消息。Consumer是消费者,负责监听Queue并取出一个消息。
消息是单向的,消息是单份的,每一种消息使用一个Queue,可以有多个Queue。A生产者产生一个消息,最多只有一个B消费者能收到此消息,其它消费者无法收到同一消息。
A生产者产生一个1号消息,放入了Q1 Queue, 若此时一个消费者都没有(消费者系统故障了),1号消息会积压在Q1 Queue当中 ,当至少有一个消费者系统启动后会收到1号消息,后来的消费者无法收到1号消息。关系哪下图。
发布/订阅模式
Publish/Subscribe模式 发布/订阅模式。
Publish是发布者,负责产生一个消息,并放入topic。topic是一个话题(本质是多个虚拟队列)。多个Subscribe是订阅者,同时在监听此topic,每一个Subscribe都能得到同一个消息。
消息是单向的,消息是 多份 的,有几个监听的订阅者就会复制出几份消息。每一种消息使用一个topic,可以有多个topic。
A发布者发布一个1号消息,放入了T1 topic,B、C两个订阅者现在刚刚开始订阅T1 topic,由于订阅晚了是无法接收到T1 topic中的1号消息的。
B、C两个订阅者现在已经订阅了T1 topic,A发布者发布一个2号消息,此时B、C两个订阅者都能收到此消息。
发布订阅模式有点类似于我们日常生活中订报纸。多个市民订阅了北京日报,每月1号报社发行当月报纸后,每个市民都会收到一份北京日报。“北京日报”相当于一个topic。发布者与订阅者就构成了一个1对多的关系。这种关系如下图所示:
应用场景--异步解耦
场景说明:用户注册后,需要发注册邮件和注册短信。当示使用MQ时业务流程如下图。
将注册信息写入数据库成功后,再发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端“注册成功”。
性能: 假设三个业务节点每个使用50毫秒,不考虑网络等其他开销,则注册业务的总耗时是150毫秒。
稳定性: 这 三个业务节点有一个节点发生故障,整个注册业务就会失败, 三个节点间的耦合度高,“ 注册业务 ”的 稳定性底。
引入MQ消息队列,对业务做异步解耦处理。采用Publish/Subscribe模式,发布/订阅模式, 用户注册成功后发出一个“用户注册完成”消息,就向客户端用户返回注册成功的提示,这时主业务完成。两个Subscribe订阅者 订阅了本消息,收到“用户注册完成”的通知,各自办理办理后续非核心业务,实现了 异步解耦 。
性能: 用户的响应时间相当于是注册信息写入数据库的时间是50毫秒。 用户注册成功消息发送成功 后直接返回。发消息用了5毫秒,因此用户的总响应时间是55毫秒。
稳定性: 这 三个业务节点,假设 发邮件和发短信的节点稳定性差 ,但核心的注册业务不会受影响。三个节点间的耦合度低,“ 注册业务 ”的 稳定性高。
扩展性:假设现在 要新增加一个业务-- 用户注册成功的同时 为此用户开通论坛账号,只需要再增加一个 Subscribe订阅者 订阅本消息,办理“ 开通论坛账号 ”业务。发布者只管在用户注册成功时发出正确的消息就可以,谁对这个消息感兴趣谁就来订阅。 发布者并不知道有几个订阅者也不需要知道。这样就完成了大型系统的功能扩展。
改造后的架构如下:
应用场景--削峰填谷
如果Producer生产消息的速度是波动变化的,时快时慢,忽高忽低,趋势就像连绵的山峰一样起伏变化。压力高峰一到,后端的业务系统可能会顶不住。MQ的 削锋填谷特性,就是使忽高忽低的压力变的平稳。
高峰时消息会堆积在MQ里等待被处理,MQ就像一个缓冲池。可使Consumer处理业务的速度变的匀速,可使后端的系统变的稳定。
Queue的堆积能力是有上限的,一旦积压的消息量超过Queue的存储能力,会丢失消息。所以整体上来看Producer生产消息的速度要小于Consumer处理业务的速度,才能持久运行,只是Producer生产消息的速度不是均匀的,有峰有谷,MQ可以 削锋填谷 。
流量削锋也是消息队列中的常用场景,
一般在秒杀或团抢活动中使用广泛
。
应用场景:秒杀活动,一般会因为流量过大,导致流量暴增后端应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。
a、可以控制活动的人数
b、可以缓解短时间内高流量压垮应用
用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。
秒杀业务根据消息队列中的请求信息,再做后续处理
不适合使用MQ的场景
需要使用返回值的情况不适合使用MQ。
A业务调用B业务,A业务需要B业务的返回值才能断续办理C业务,A和B之间就不能使用MQ。
经过MQ异步解耦后,消息是单向的,不能有返回值 。
MQ选型对比文档