RabbitMQ|青训营笔记

58 阅读3分钟

这是我参与「第五届青训营」笔记创作活动的第11天。

在前段时间里运用RabbitMQ实现了大项目的聊天功能,但是对RabbitMQ的底层原理理解还不够透彻,今天学习了RabbitMQ的应用场景、RabbitMQ如何实现消息的可靠性投递和如何保证RabbitMQ消息的幂等性问题。

为什么要用 MQ

1.流量消峰:

举个例子,如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单时绰绰有余,正常时段我们下单一秒后就能返回结果。但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。 简单来说: 就是在访问量剧增的情况下,但是应用仍然不能停,比如“双十一”下单的人多,但是淘宝这个应用仍然要运行,所以就可以使用消息中间件采用队列的形式减少突然访问的压力

2.应用解耦:

以电商应用为例,应用中有订单系统、库存系统、物流系统、支付系统。用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障,都会造成下单操作异常。当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成。当物流系统恢复后,继续处理订单信息即可,中间用户感受不到物流系统的故障,提升系统的可用性。

RabbitMQ消息的可靠投递

RabbitMQ具有其独特的消息补偿机制,具体实现流程如下图所示:

image.png

  1. 首先producer操作自己的数据库,发送一条消息,将这个消息存储在Q1这个队列中。
  2. 然后Consumer拿Q1中的消息去消费,同时操作自己的数据库完成一些业务的处理,并异步发送确认消息到Q2中。
  3. 其中Q2是一个被回调检查服务监听的队列,回调检察服务会将Q2中的消息存储到MDB中。
  4. 过了一段时间以后producer发送了延迟消息到Q3队列中,Q3也是一个被回调检查服务监听的队列,这个时候回调检查服务会将Q3中的消息与刚刚写入MDB中的消息进行比对,如果比对成功则说明消息被消费了。如果比对不成功,则重新调用producer发送消息。
  5. 系统还具有定时检查服务,会定时对DB和MDB中的信息进行比对,如果比对失败则重新发送消息。

RabbitMQ消息的幂等性问题

在RabbitMQ中,消息的幂等性保障为:消费多条相同的消息,得到于消费该消息一次相同的结果。

可以通过使用数据库的乐观锁来保证消息的幂等性:

首先,在消息的字段中加入一个新的字段version。

其次,每次在消费queue中的消息,触发update操作的时候,令version = version+1

当接受到这样的一条消息的时候,第一次SQL语句会执行成功,而第二次SQL语句不会执行成功。具体原理见下图中的SQL语句。

image.png

image.png