场景一:异步&解耦
用户发送注册请求,可能出现响应不及时的问题,同时短信功能与用户中心耦合,非核心影响核心功能。
加入消息队列可以实现解耦,同时在用户点击注册后前端能立即反馈,并将注册请求放入消息队列,等待后续的任务服务而不影响前端。
场景二:消峰
高并发场景下,面对突然出现的请求峰值,非常容易导致系统变得不稳定,比如大量请求访问数据库,会对数据库造成极大的压力,或者系统的资源 CPU 、IO 出现瓶颈。
以网约车下单举例,采用MQ,修改订单时直接修改MQ,后续再修改数据库,可以达到消峰目的。
场景三:消息总线
以彩票服务系统为例,每一个环节都需要不同的服务处理,每个系统都有自己独立的表,业务功能也相对独立。假如每个应用都去修改订单主表的信息,那就会相当混乱了
而采用MQ作为消息总线,可以很好解耦。
场景四:延时任务
以美团订单为例,用户下单,假如没有立即支付,进入订单详情会显示倒计时,如果超过支付时间,订单就会被自动取消。
用MQ可以解决该场景:订单服务生成订单后,发送一条延时消息到消息队列。消息队列在消息到达支付过期时间时,将消息投递给消费者,消费者收到消息之后,判断订单状态是否为已支付,假如未支付,则执行取消订单的逻辑。
场景五:广播消费
使用广播消费模式时,每条消息推送给集群内所有的消费者,保证消息至少被每个消费者消费一次。
有两种常见场景:消息推送和缓存同步
消息推送
以打车机制为例,派单服务是生产者,将派单数据发送到 MetaQ;推送服务是一个 TCP 服务(自定义协议),同时也是一个消费者服务。
司机打开司机端 APP 后,APP 会通过负载均衡和推送服务创建长连接,推送服务会保存 TCP 连接引用。每当有新的订单,将会把信息发送到MQ,每个推送服务都会消费到该消息,推送服务判断本地内存中是否存在该司机的 TCP channel , 若存在,则通过 TCP 连接将数据推送给司机端。
缓存同步
高并发场景下,很多应用使用本地缓存,提升系统性能。以下案例,应用 A 启动后,作为一个 RocketMQ 消费者,消息模式设置为广播消费。为了提升接口性能,每个应用节点都会将字典表加载到本地缓存里。
当字典表数据变更时,可以通过业务系统发送一条消息到 RocketMQ ,每个应用节点都会消费消息,刷新本地缓存。
场景六:分布式事务
以电商交易场景为例,用户支付订单这一核心操作的同时会涉及到下游物流发货、积分变更、购物车状态清空等多个子系统的变更。
传统方法
当用户支付订单后,向下游多个子系统发送消息,为了保证结果一致性,典型方案是基于 XA 协议的分布式事务系统来实现,将四个调用分支封装成包含四个独立事务分支的大事务。但是缺点是多分支环境下资源锁定范围大,并发度低,随着下游分支的增加,系统性能会越来越差。
基于普通消息方案:一致性保障困难
该方案中消息下游分支和订单系统变更的主分支很容易出现不一致的现象,例如:
- 消息发送成功,订单没有执行成功,需要回滚整个事务。
- 订单执行成功,消息没有发送成功,需要额外补偿才能发现不一致。
- 消息发送超时未知,此时无法判断需要回滚订单还是提交订单变更。
基于 RocketMQ 分布式事务消息:支持最终一致性
上述方法缺点本质上是由于普通消息无法像单机数据库事务一样,具备提交、回滚和统一协调的能力。
而基于 RocketMQ 实现的分布式事务消息功能,在普通消息基础上,支持二阶段的提交能力。将二阶段提交和本地事务绑定,实现全局提交结果的一致性。
场景七:数据中转枢纽
常见于日志采集