概念

幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次
image.png

  • select查询天然幂等
  • delete删除也是幂等,删除同一个多次效果一样
  • update直接更新某个值的,幂等
  • ☆ update更新累加操作的,非幂等
  • ☆ insert非幂等操作,每次新增一条

    解决方法

    前端
  1. 前端js提交禁止按钮可以用一些js组件

数据库

  1. 唯一索引 — 防止新增脏数据
  2. 乐观锁 — 基于版本号version实现, 在更新数据那一刻校验数据

这种在大数据量和高并发下效率依赖数据库硬件能力,可针对非核心业务

  1. 悲观锁 — 获取数据的时候加锁(锁表或锁行)

使用select … for update ,这种和 synchronized 锁住先查再insert or update一样,但要避免死锁,效率也较差针对单体 请求并发不大 可以推荐使用

应用层

  1. token机制 — 下次请求的时候在请求的header体中加上这个token,后台进行验证,如果验证通过删除token,下次请求再次判断token
  2. 分布式锁 — redis(jedis、redisson)或zookeeper实现

唯一编号去重

只要请求有唯一的请求编号,
用户ID:接口名:请求参数
String KEY = “dedup:U=”+userId + “M=” + method + “P=” + reqParam;
把请求参数(JSON)按KEY做升序排序,排序后拼成一个字符串,作为KEY值呢?但这可能非常的长,所以我们可以考虑对这个字符串求一个MD5作为参数的摘要,以这个摘要去取代reqParam的位置。

那么就能借用Redis做这个去重——只要这个唯一请求编号在redis存在,证明处理过,那么就认为是重复的


redis + token机制实现接口幂等性校验

1.拦截器2.AOP
获取token的控制器TokenController,存入redis,设置超时

TestController, 注意@ApiIdempotent注解, 在需要幂等性校验的方法上声明此注解即可, 不需要校验的无影响