天天看点

RabbitMQ应用问题——消息补偿机制以及幂等性的保证简单介绍RabbitMQ应用问题​​​​​​​消息补偿机制消息幂等性保证

大伙可以到我的RabbitMQ专栏获取更多信息

RabbitMQ应用问题

  • 消息可靠性的保障
    • 消息补偿机制
  • 消息的幂等性保障
    • ​​​​​​​乐观锁解决方案

​​​​​​​消息补偿机制

RabbitMQ应用问题——消息补偿机制以及幂等性的保证简单介绍RabbitMQ应用问题​​​​​​​消息补偿机制消息幂等性保证

这个图看起来好像很复杂,其实只做到了三件事情:

  • 发消息
  • 收到消息确认
  • 检查比对是不是收到消息了

详细说明消息补偿流程

  1. 发生业务操作,业务数据写入数据库
  2. 生产者将消息发送给MQ的队列Q1
  3. 发送了一条与step2中一摸一样的延迟消息到对了Q3
  4. 消费者监听Q1,获取到了step2中发送的业务消息
  5. 消费者在收到生产者的业务消息后,发送了一条确认消息(记录收到的消息信息)到Q2
  6. 回调检查服务监听了Q2,获取到了消费者发送的确认消息
  7. 回调检查服务将这条确认消息写入数据库等待之后的比对
  8. Q3中的延迟消息延迟时间已到,被回调检查服务接收到,之后就拿着这条延迟消息在数据库中比对,如果比对成功,证明消费者接收到了生产者的业务消息并处理成功(如果不处理成功谁会傻了吧唧发送确认消息呢);如果比对失败,证明消费者没有接收到生产者的业务消息,或者说消费者接收到了业务消息之后始终没有处理成功相关的业务并发送确认消息。这时回调检查服务就会调用生产者的相关业务接口,让生产者再次发送这条失败的消息
  9. 有一种最极端的情况,step2和step3的消息都发送失败了或者说在消息传递过程中发生意外丢失了!定时检查服务会一直轮询保存确认消息的数据库中的消息数据,并于生产者的业务数据库中的业务数据进行比对,如果两者比对数量一致,则代表业务执行没有问题;如果比对不一致,确认消息数据库的数据量小于生产者业务数据量的话,就证明消费者没有接收到生产者发送的消息。这时定时检查服务会通知生产者再次发送消息到MQ的队列Q1

消息幂等性保证

什么是幂等性?

在计算机领域简单的讲就是指一次和多次请求某一个资源,等于该资源本身应该具有同样的结果。说人话:任意多次执行对资源的操作,对资源本身产生的影响于与执行一次对资源的操作是一样的。在MQ中指消费多条相同的消息产生的结果与第一次消费该消息的结果相同。比如说转账案例:我第一次通过手机银行发送的转账500申请由于网络或者说银行系统负载高等原因,导致没有执行成功,我个人又点了很多次转账的按钮,但是银行的系统必须保证我只转出去了500。

幂等性更详细更完整的解释请大伙自行搜索了解哈。

乐观锁机制

关于解决幂等性问题的方案有很多,此处配合RabbitMQ的消息补偿机制就介绍一下常见的乐观锁机制,数据库中乐观锁的运用就不做过多解释了,相信看这篇文章的小伙伴都应该知道哈。

在刚才所讲的消息补偿机制中,如果消费端除了某种问题导致无法获取到业务数据会触发以下两种补偿机制:

  • 当确认消息发送失败,回调检查服务会用延迟消息比对数据库中是否存在确认消息,如果没有会通知生产者继续发送同样的业务数据
  • 当定时检查服务检查确认消息小于业务数据的时候也会调用生产者重发业务消息到MQ

这时候队列Q1中可能会有多条一摸一样的消息,当消费者的服务恢复正常之后,Q1队列中这些一样的消息都会被Q1读取并进行业务处理。此时如果消费者没有幂等性的保证的话,就会出现“多扣钱”的问题。

此时乐观锁就派上用场了,通过每次消息中带有的version信息,来判断该业务操作是否能执行成功:

-- 消息内容:
{id = 1, money = 500, operation = subtract, version = 1}

-- 第一次执行
update account set money = money - 500, version = version + 1 where id = 1 and version = 1;

--第二次执行的时候,version = 2,所以这条sql无法匹配到数据就不做扣钱处理了
update account set money = money - 500, version = version + 1 where id = 1 and version = 1;