为什么要使用消息队列?
我们以一个电商平台为例:
用户下一个订单,那么接下来的后台动作将会有
- 在数据库里创建一条订单数据
- 库存数减一
- 给用户加积分
- 给用户发优惠券
无论是单体/分布式的微服务,这些流程一般都是同步进行的,如下图。
但是同步的方式会存在一个问题:
造成的系统开销--响应时间比较大的。2-5秒
服务在同步的过程中,要保证每个服务都执行完,整个链路才执行完,因为网络等其它问题,整个链路成功执行完的成功率会受影响,会存在性能和稳定性的问题,导致用户体验较差。
那么我们如何才能优化呢?使用异步的方式。
这时,我们引入“消息队列”。
当用户下订单时,我们就往消息队列中发送一条消息,发送消息成功后,我们就直接返回订单创建成功了,如图。
这样的话 我们500毫秒就可以创建成功了。
在消息队列中存储有多个带有商品信息和请求信息的队列,上游发送消息,下游订阅消息队列中的消息,这样异步处理起来速度就会快很多,明显提升系统的吞吐量;即使有服务失败,也可以通过分布式事务解决方案来保证最终是成功的。
针对于同步的通信方式来说,异步的方式,可以让上游快速成功,极大提高了系统的吞吐量。而且在分布式系统中,通过下游多个服务的分布式事务的保障,也能保障业务执行之后的最终一致性。
消息队列具体解决的什么问题呢?
消息队列解决具体问题其实是通信问题!
Message Queue (MQ),消息队列中间件。很多人说:MQ通过将消息的发送和接收分离来实现应用程序的异步和解耦,这个给人的感觉是-------MQ是异步的,是用来解耦的,其实这个只是MQ的效果,而不是MQ的目的。MQ真正的目的是为了通讯,屏蔽地层复杂的通信协议。定义了一套应用层的、更加简单的通讯协议。一个分布式系统中的两个模块之间的通讯,要么是HTTP,要么是自己开发的(rpc)TCP,但是这两种协议其实都是原始的协议。http协议很难实现两端通讯--模块A可以调用模块B,模块B也可以调用模块A,tcp就更加原始了,粘包、心跳、私有协议,想想就蛋疼。
MQ带给我们的“协议”不是具体的通讯协议,而是更高层次的通讯模型。它定义了两个对象
- 发送数据的生产者
- 接收数据的消费者
提供一个SDK让我们可以定义自己的生产者和消费者实现消息通讯而无视低层协议。