幂等性指一次和多次请求某一个资源,对于资源本身应该具有同样的结果。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。
在MQ中指,消费多条相同的消息,得到与消费该消息一次相同的结果。
消息发送还是之前的消息补偿流程图,而这里消息幂等性保障主要是依赖 DB 的乐观锁机制。
需求:
下面我们需要进行一个订单扣除金额的幂等性保障,例如我们发起扣除500元的消息,如果发出了多条扣除消息,到最后只允许扣除500元,不允许多次扣除。
实现思路:
当第一次发送消息,内容:id=1,money=500,version=1
当时此时 Consumer 发生了故障,要求 Producer 再次发送消息,此时 Consumer 将会收到两条消息:
id=1,money=500,version=1
id=1,money=500,version=1
Consumer此时收到两条相同的消息,为了避免重复执行,SQL更新需要设置 version 的变更:
-- 第一次执行:version=1,执行结果生效,扣除了500元
update account set money = money - 500 , version = version + 1
where id = 1 and version = 1
-- 第二次执行:version=2,由于where条件查询不到 version=1 的结果了,所以第二次执行将失败
update account set money = money - 500 , version = version + 1
where id = 1 and version = 1