出现场景
- http接口前端瞬间双击提交
- 消息队列重复消费
- RPC接口网络超时重试
带来的问题
- 用户支付多笔订单。
- 用户收到多条通知。
- 用户的流水存在一样的历史记录。
处理方式
思路
任何一个需要幂等的请求都需要有一个唯一标识,否则无法处理幂等。
- 更新库存,采用stock x -1操作,而应该采用(set x - 1)+ (where stock = x)
- 下单支付,应该采用where status=UNPAY进行重复请求的过滤。或者通过支付流水是否存在进行判断。
- 添加流水,应该对订单Id进行唯一性保证,也在db层保证,防止一条订单存在多笔支付流水。
- 删除资源,删除不存在的资源,直接返回true。
- 操作主体维度加锁,要么从业务维度挑选出主体,或者采用token机制。
- 读:天然幂等
- 删:删除不存在的资源返回成功。
- 增:设定唯一键
- 改:
- 分布式锁:通过redis、zk进行加锁。
- 数据库锁:
- 悲观锁:对需要操作的数据记录加X锁。
- 乐观锁:增加version字段或者针对递增递减字段,将原字段值机加入where约束。
- 状态机:类似乐观锁,适用于数据表存在状态机设置,将原状态机加入where约束。