介绍:
幂等就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的。消息幂等是消费者在消费消息中间件的时候,有可能会出现重复消费的场景;所以消费者的业务代码要做好幂等的控制。
消息中间件是分布式系统常用的组件,无论是异步化、解耦、削峰等都有广泛的应用价值。基于消息的投递可靠(消息不丢)是优先级更高的,所以消息不重的任务就会转移到应用程序自我实现。
解决方案:
- 简单的消息幂等解决方案
select * from t_order where order_no = 'order123'
if(order != null) {
return ;//消息重复,直接返回
}
并发不高或者没有并发的场景下,效果不错。
一旦出现高并发的场景,IF条件判断那里就会出现两个线程判断都满足的情况;也就是存在竞态条件。
可以采用悲观锁(for update)和乐观锁的方式去解决,这两种方法都是基于业务表去做的,增加了业务开发的复杂度,特别是一个业务系统里面有很多地方都是依赖于MQ消息的。另外,如果并发量很大的话,性能也会受到很大影响。
- 基于关系数据库事务
这里引入了一个消息表。
开启事务
插入消息表(处理好主键冲突的问题)
更新订单表(原消费逻辑)
提交事务
局限性:消息的消费必须是仅依赖于关系型数据库;数据库必须是在一个库,跨库无法解决;
-
基于消息表的非事务方案
依旧使用消息表,但是不依赖事务,而是针对消息表增加消费状态(消费完成、消费中),查询判断。
利用MQ的延迟消费,防止消息丢失。
image.png
总结:
最后再加上监控、报警、补偿,应该足矣。好的东西,要记录下来,好记性不如烂笔头。
后续补充:
两种场景:更新状态失败、删除消费表记录失败
处理方案:适当的重试+定时任务删除存在一定时间(10分钟)的数据。
执行业务逻辑:这块地方也要适当的做一下简单的幂等。
网友评论