什么是MQ(消息队列)?
真实的业务场景
订单履约系统是所有电商公司业务核心中的核心,一般来说,它的整体业务流程、核心业务流程和非核心业务流程整体上都是这样子的的。



在应用规模和用户量都还不大的情况下,即使是非常简单的系统架构,也能轻松处理大量的查询请求。
虽然单节点架构不如分布式那么能扛压,也不像分布式那样可以伸缩自如,但也不要低估了它。

在现在计算机硬件配置越来越豪华的情况下,即使单节点的计算机,也能轻松应对上万并发的请求。优化应该是自然而言发生的,不需要强行揠苗助长,给自己找麻烦。
当订单支付成功后,需要执行一系列的后续业务操作,一般它们包括但不限于下面这些。

回调通知:和用户系统挂钩,通知用户支付成功,以及商家开始拣货、打包、发货等后续信息。
扣减库存:向仓储管理系统(WMS)发消息,锁定并扣除有效库存,否则通过回调通知用户付款失败,返还资金。
累计积分:和运营系统挂钩,改变用户积分及其相应等级、风险评估等级等相关数据。
发放红包:和促销系统挂钩,改变用户红包账户余额并发送通知。
推送通知:承接所有系统的所有接收和发送的消息。
更新状态:更新所有交易相关的业务数据,并持久化到数据库中。
以上这些需要都在1~2秒内完成。而如果用户不满意,那么刚才那些动作都要重新再来一遍,只不过过程是相反的。

过去很多初创公司的系统都是以同步的方式执行各种业务功能和用户请求的,这种方式即使网络很慢,效率很低,也都还在可控范围。

但如果是调用外部系统就麻烦了。
如果第三方系统支付或退款异常,或者
卡住
了,该怎么办?如果用户下单后迟迟不付款怎么办?
如果第三方仓储系统崩溃了,订单系统要等它恢复了才能继续往下执行吗?
诸如此类的问题有很多,每一个都有可能造成系统无限期地等下去。
异步与消息队列
系统除了以同步的方式执行,还可以以另一种称为异步
的方式执行。

例如,在上面的图中,系统A
不必等系统B
有了响应再继续往下执行,而是向系统B
发了个消息,相当于说:“交给你了,我先走了”,然后就直接向用户报告结果去了。
当到用户真的想看那个结果的时候,系统A
再以回调或者接口调用的方式从系统B
那里拿到用户想要的结果。
这相当于打了一个时间差。
所以,系统A
向系统B
发送消息的那个组件,就叫做消息队列(Message Queue),或者简称MQ
。
有消息队列以后,系统A
和系统B
之间的交互方式有些不同了。
系统A
不必等到系统B
有了结果再执行下一步,而是可以先接着往下执行,等系统B
有了执行完了再回过头来拿结果。通过引入新的消息队列组件,不但不会拖累各个自身的执行效率,反而还实现了两个系统之间的解耦,让它们之间不再相互影响,或将彼此的影响程度降到最低。
因为消息队列自己有固定的消息消费速率(也就是一段时间内消费消息的速度),即使以再快的速度向它发送消息,但它的消费速率是不会变的。所以,实际上,它还起到了一个流量削峰的作用。

通过消息队列,那些超过系统处理能力的请求,将会像水池中的水那样被蓄起来
,待到系统压力不那么有能力处理它们时再来执行,这也相当于打了一个时间差。这种方式虽然延长了请求响应的时间,但总比直接丢弃它们要好。
目前主流的消息队列中间件有下面几种。
对比项 | 性能 | 数据 | 功能 | 优势 | 劣势 | 适用场景 |
---|---|---|---|---|---|---|
Kafka | 高 | 可能丢失 | 单一 | 超高吞吐量 | 允许数据丢失 功能过于简单 强制数据完整时性能下降 | 日志采集 |
RocketMQ | 高 | 保证不丢失 | 多 | 功能强大 可视化管理 一线大厂都在用 高并发能力极强 支持数据0丢失的配置 Java语言开发,便于改造 | 官方文档简单 | 大中小型公司都适用 |
RabbitMQ | 低 | 保证不丢失 | 较多 | 功能强大 可视化管理 落地案例多 | 高并发能力较弱 erlang语言开发,不便于改造 | 中小型公司,无超高并发场景 |
关注公众号后回复 rocketmq
即可获得RocketMQ
栏目剩余文章的访问密码。
