消息队列概述
消息队列是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。
通过提供消息传递和消息排队模型,它可以在分布式环境下提供应用解耦、弹性伸缩、冗余存储、流量削峰、异步通信、数据同步等等功能,其作为分布式系统架构中的一个重要组件,有着举足轻重的地位。
特点
异步处理
异步处理就是多个任务的串行执行优化为多个任务的异步并行处理。
消息发送者将消息发送到一条 虚拟的通道(主题 或 队列)上,且无需等待响应。消息消费者会订阅或监听该通道。消费者不需要对生产者进行同步响应。
解耦
主要体现在
- 消费者和生产者不必了解对方、只需要确认消息
- 发送者和接受者不必同时在线
消息队列的的传输模式
点对点
点对点模型用于消息生产者和消息消费者之间点到点的通信。消息生产者将消息发送到由某个名字标识的特定消费者。这个名字实际上对于消费服务中的一个 队列(Queue
),在消息传递给消费者之前它被 存储 在这个队列中
特点:
- 每个消息只用一个消费者
- 发送者和接受者没有时间依赖
- 接受者确认消息接受和处理成功
发布/订阅
发布者/订阅者 模型支持向一个特定的 消息主题 生产消息。0
或 多个订阅者 可能对接收来自 特定消息主题 的消息感兴趣。
在这种模型下,发布者和订阅者彼此不知道对方。多个消费者可以获得消息,在发布者创建订阅,以便订阅者消费。订阅者必须保持持续的活动状态并接收消息。当订阅者 未连接时,发布的消息将在订阅者重新连接时重新发布
特性:
- 每个消息可以有多个订阅者
- 客户端只有订阅后才能接收到消息
- 持久订阅和非持久订阅
注意:
- 发布者和订阅者有时间依赖:接受者和发布者只有建立订阅关系才能收到消息;
- 持久订阅:订阅关系建立后,消息就不会消失,不管订阅者是否都在线;
- 非持久订阅:订阅者为了接受消息,必须一直在线。 当只有一个订阅者时约等于点对点模式
消息队列应用场景
消息队列的场景有很多,最常用的几种
- 应用程序松耦合
- 异步处理模式
- 发布与订阅
- 最终一致性
- 错峰流控
- 日志缓冲
如果需要强一致性,关注业务逻辑的处理结果,则使用 RPC
显得更为合适。
异步处理
非核心流程异步化,减少系统响应时间,提高吞吐量。如网站用户注册后推送邮件进行账户确认。
解耦
- 系统之间不是 强耦合的,消息接受者 可以随意增加,而不需要修改消息发送者的代码。消息发送者 的成功不依赖 消息接受者(比如:有些银行接口不稳定,但调用方并不需要依赖这些接口)
- 不强依赖于非本系统的核心流程,对于非核心流程,可以放到消息队列中让消息消费者去按需消费,而 不影响核心主流程
最终一致性
最终一致性不是消息队列的必备特性,但确实可以依靠消息队列来做最终一致性的事情
- 先写消息再操作
- 确保操作完成后再修改消息状态
- 定时任务补偿机制可实现消息可靠发送接收、业务操作的可靠执行
- 要注意消息重复与幂等设计
- 只要消息队列不保证
100%
不丢消息,那么理论上最终一致性无法实现 - 哪怕只丢千分之一的消息,业务也必须用其他的手段来保证结果正确
广播
生产者/消费者模式,只需要关心消息是否送达队列,至于谁希望订阅和需要消费,是下游的事情,无疑极大地减少了开发和联调的工作量
流量削峰和流控
在特定场景下(如秒杀),会有请求聚集的情况,短时间会有大量的请求。为了节省服务器资源,不可能时时都提供最大化的资源能力来支持短时间的高峰请求。所以需要设计出能够削弱短时间大量请求的架构。
当上下游系统处理能力存在差距的时候(接受请求的速度>处理请求的速度),利用消息队列做一个通用的 “漏斗”,进行限流控制。在下游有能力处理的时候,再进行分发,这是一套相对较通用的方式
日志处理
将消息队列用在日志处理中,如将日志进行集中收集,用于计算 PV、用户行为分析
消息通讯
消息队列一般都内置了高效的通信机制,因此也可以用于单纯的 消息通讯,比如实现 点对点消息队列 或者 聊天室 等。
消息队列的推拉模型
说明
模型 | 说明 |
Push推消息模型 | 消息生产者 将消息发送给 消息队列,消息队列 又将消息推给 消息消费者 |
Pull拉消息模型 | 消息生产者 将消息发送给 消息队列,消息消费者 从 消息队列 中拉该消息 |
区别
模型 | Push | Pull |
服务端 | 消息存储 处理请求 保存推送轨迹 保存订阅关系 消费者负载均衡 集中式 | 消息存储 处理请求 分布式 |
客户端 | 处理和响应请求 | 处理和响应请求 保存pull状态,如拉去位置的偏移量 offset 异常情况下的消息暂存个recover |
实时性 | 较好,收到数据可立即发送给客户端 | 取决于pull的时间间隔 |
消费者保障 | 消费者故障情况下,重复推送耗费资源 保存推送轨迹压力很大 | 消费者故障,对服务器无影响 |
其他 | 对消息推送有更多控制,能实现多样化的推送机制 当消费者数量增多的时候,推送压力大,性能天花板 消费者处理能力差异,导致堆消息 | 需要在客户端实现消息过滤,浪费资源 需要在不同客户端之间协调,做负载均衡 |