出现场景

  • http接口前端瞬间双击提交
  • 消息队列重复消费
  • RPC接口网络超时重试

带来的问题

  1. 用户支付多笔订单。
  2. 用户收到多条通知。
  3. 用户的流水存在一样的历史记录。

处理方式

思路

任何一个需要幂等的请求都需要有一个唯一标识,否则无法处理幂等。

  1. 更新库存,采用stock x -1操作,而应该采用(set x - 1)+ (where stock = x)
  2. 下单支付,应该采用where status=UNPAY进行重复请求的过滤。或者通过支付流水是否存在进行判断。
  3. 添加流水,应该对订单Id进行唯一性保证,也在db层保证,防止一条订单存在多笔支付流水。
  4. 删除资源,删除不存在的资源,直接返回true。
  • 操作主体维度加锁,要么从业务维度挑选出主体,或者采用token机制。
  • 读:天然幂等
  • 删:删除不存在的资源返回成功。
  • 增:设定唯一键
  • 改:
    • 分布式锁:通过redis、zk进行加锁。
    • 数据库锁:
      • 悲观锁:对需要操作的数据记录加X锁。
      • 乐观锁:增加version字段或者针对递增递减字段,将原字段值机加入where约束。
      • 状态机:类似乐观锁,适用于数据表存在状态机设置,将原状态机加入where约束。