幂等

4 分钟阅读 541 字 + 474 词
幂等是 多次执行的影响和一次执行的影响是一样 的。
image-20241018152437048
方案一:
  • 数据库select +insert+主键唯一索引冲突
    根据 唯一流水号bizSeq字段(uuid) ,先select一下 数据库的流水表
    如果数据 已经存在 ,就 拦截是重复请求 ,直接返回成功
    如果数据不存在,就执行insert插入,如果Insert成功,则直接返回成功,如果insert产生主键冲突,则捕获异常,接着直接返回成功。
    存在业务侵入,需要提供写数据库操作和查数据库操作,影响性能 )
方案二:
  • 方案一会查一下流水表,但是如果重复的概率比较低,我们可以直接插入请求,利用 主键/唯一索引冲突 ,去判断是重复请求。
方案三:
  • 状态机幂等 直接通过业务来判断,给表中加一个 状态字段 ,写sql的时候带上这个状态利用where语句设置
    0-待处理,1-处理中,2-成功,3-失败
    ==sql语句: update transfer_flow set status=2 where biz_seq='666' and status=1 ;==
    影响行数是否等于1?如果等于1代表正常处理请求,如果不等于1,也返回成功
方案四:
  • 使用token机制 ,服务器在表单提交前生成一个token,发给前端, 前端提交的时候携带这个token ,然后到服务器中的redis中进行判断是否存在,如果 存在,将这个token删掉 ,那么之后的重复提交由于这个token已经被删除,就不能往后执行了。
方案五:
  • 单独搞个防重表,利用主键索引唯一性,如果插入防重表冲突直接返回成功,如果插入成功,去处理请求。
方案六:
  • 利用数据库悲观锁,select ... for update (不推荐的思路)
    如果查到的状态是处理中,就处理完业务,再更新状态为完成,如果不是处理中,就直接返回。
    或者使用乐观锁的思想,利用版本号,第一次请求版本号一定是1.
方案七:
  • 在后端利用redis使用setnx,设置key,当设置过了就会返回false,并且设置过期时间。

目录