抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

接口幂等性

问题引入

  • 提交订单按钮如何防止重复提交
  • 表单的录入页如何防止重复提交
  • 微服务接口, 客户端重试时, 会对业务数据产生影响吗

概念

  • 幂等性:f(f(x)) = f(x)
  • 幂等元素运行多次, 还等于它原来的运算结果
  • 在系统中, 一个接口运行多次, 与运行一次的效果是一致的

什么情况下需要幂等性

  • 重复提交、接口重试、前端操作抖动等
  • 业务场景:用户多次点击提交订单, 后台应只生成一个订单
  • 业务场景:支付时, 由于网络问题重发, 应该只扣一次钱
  • 并不是所有的接口都要求幂等性, 要根据业务而定

保证幂等性的策略

幂等性的核心思想:通过唯一的业务单号保证幂等性

  • 非并发情况下, 查询业务单号有没有操作过, 没有则执行操作

  • 并发的情况下, 整个操作过程加锁

  • Select操作:不会对业务数据又影响, 天然幂等

  • Delete操作:第一次已经删除, 第二次也不会有影响

  • Update操作:更新操作传入数据版本号, 通过乐观锁实现幂等性

  • Insert操作:此时没有唯一业务员单号, 使用Token保证幂等

  • 混合操作:找到唯一业务单号, 有则可使用分布式锁, 没有可以通过Token保证幂等

Delete 操作的幂等性

  • 根据唯一的业务号去删除.
  • 第一次删除时, 已经将数据删除.
  • 第二次再次执行时, 由于找不到记录, 返回的结果是0, 对业务数据, 没有影响. 可在删除前进行数据的查询.
  • 删除操作没有唯一的业务号, 则要看具体的业务需求
  • 例如:删除所有审核未通过的商品, 在第二次执行前, 又有新的商品未审核通过, 执行第二次删除操作, 新的未审核通过的商品要不要删除.
  • 根据业务需求而定

Update 操作的幂等性

  • 根据唯一业务号更新数据的情况
  • 用户查询出要修改的数据, 系统将数据返回页面, 将数据版本号放入隐藏域
  • 用户修改数据, 点击提交, 将版本号一同提交给后台
  • 后台使用版本号作为更新条件
  • update set version = version + 1, xxx=${xxx} where id=xxx and version=${version}
  • 使用乐观锁与update行锁, 保证幂等
  • 更新操作没有业务单号, 可使用token机制

Insert 操作的幂等性

  • 唯一业务号的Insert操作, 例如:秒杀, 商品Id+用户Id
  • 可通过分布式锁, 保证接口幂等
  • 业务执行完成后, 不进行行锁释放, 让其过期自动释放
  • 没有唯一业务号的Insert操作, 比如:用户注册, 点击多次
  • 使用Token机制, 保证幂等性
  • 进入到注册页, 后台统一生成Token, 返回前台隐藏域中
  • 用户在页面点击提交时, 将Token一同传入后台
  • 使用Token获取分布式锁, 完成Insert操作
  • 执行完成后, 不释放锁, 等待过期自动释放

混合操作的幂等性

  • 混合操作, 一个接口包含多种操作
  • 同样可以使用Token机制

评论