2020年2月12日 作者 zeroheart

幂等性的相关方法

相同的操作,执行一次或者多次应该是一样的结果

1.查询具有天然的幂等性,用主键删除也是幂等的

2.实现幂等性的相关方法:

2.1
服务器token
服务器返回token,存到redis,客户端带token请求,请求后删除token,如果redis存在token为第一次请求,不存在则为重复请求。
请求数量多,占用资源

2.2特殊场景

2.2.1
insertOrUpdate

唯一索引约束,产品分类表,产品id和分类id加唯一索引。
insert into goods_category (goods_id,category_id,create_time,update_time)
values(#{goodsId},#{categoryId},now(),now())
on DUPLICATE KEY UPDATE
update_time=now();

2.2.2
多版本控制
1)update table_xxx set name=#name#,version=version+1 where id=#id# and version=#version#
2)update table_xxx set avai_amount=avai_amount-#subAmount# where id=#id# and avai_amount-#subAmount# >= 0
记得添加主键id或者唯一索引,否则可能锁表

2.2.3
状态机控制
这种方法适合在有状态机流转的情况下,比如就会订单的创建和付款,订单的付款肯定是在之前,这时我们可以通过在设计状态字段时,使用int类型,并且通过值类型的大小来做幂等,比如订单的创建为0,付款成功为100。付款失败为99

在做状态机更新时,我们就这可以这样控制
update order set status=#{status} where id=#{id} and status<#{status}

例子中状态是递增的

2.2.4
防重表
请求带唯一标示,插入防重表,在同一个事务中处理业务,如果防重表插入报错,整个业务也会回滚。

实践:
对外提供接口为了支持幂等调用,接口有两个字段必须传,一个是来源source,一个是来源方序列号seq,这个两个字段在提供方系统里面做联合唯一索引,这样当第三方调用时,先在本方系统里面查询一下,是否已经处理过,返回相应处理结果;没有处理过,进行相应处理,返回结果。注意,为了幂等友好,一定要先查询一下,是否处理过该笔业务,不查询直接插入业务系统,会报错,但实际已经处理了。