幂等性的定义
就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品使用支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条。
请求层面:读请求、写请求
其中读请求没有影响数据变化不需要做幂等性
微服务层面:负载均衡、api网关、业务逻辑层、数据访问层
其中负载均衡、api网关、业务逻辑层没有影响数据变化不需要做幂等性
总结:上面的范围里只有数据访问层和写请求
Insert
需要做幂等性
Update
直接更新某个值的:不需要做幂等性
累加操作等计算式的更新:需要做幂等性
Delete
重复删除结果是一样:不需要做幂等性
没有最优的方案只有最适合的,因为这个和业务的逻辑强相关,所以就简单列举通用的方案
数据字段增加唯一索引
优点:实现简单方便
缺点:影响数据库性能不适合该字段会被频繁更新的场景,唯一索引比普通索引在写操作上开销会大很多
insert时使用临时表查询判断
insertintosys_user(name,password)select'admin','123456'fromdualwherenotexists(select1fromsys_userwherename='admin');
优点:不需要创建唯一索引,语法相对通用(mysql和oracle)
缺点:写操作会增加一次select子查询开销,增加sql语法的复杂度可读性较差
细粒度分布式锁+select + insert
意思就是先加一个细粒度的分布式锁,然后select查一下是否存在,不存在再insert
例子可参考文档:开发说明中的方法级幂等性
优点:性能影响较少,使用的是细粒度锁,所以只有重复提交记录时才会阻塞
缺点:写操作会增加一次select开销,实现难度相对较大因为需要分布式细粒度锁
这个需要结合具体业务来设计方案,常用的场景可通过版本号的方式来控制
1 . 在表里面添加version字段
altertablesys_useraddversionintdefault0;
然后更新的时候通过这个version来判断是否为过期无效操作,这是乐观锁的一种思路
updatesys_usersetage=age+1,version=version+1whereversion=xx