幂等性与并发(表单重复提交和并发增删改及校验唯一操作场景)

并发更新操作

     先说乐观锁version 表t1 字段v值为1,
     先select当前版本号1
     同时更新操作update set v=v+1 where v=1
     第一个执行的将v值更新为2,更新结果为1条记录
     其他并发重复操作因数据库v值已更新为2,where 2=1更新0条记录,判断为过期无效操作
     timestamp方式同理(建议用timestamp,方便大数据或跨库进行同步处理)
     删除操作可不考虑并发,因为多删几次,结果是一样的,这条记录不存在

并发插入操作(单用户重复提交)

0、因为在新增数据时,没有旧值进行乐观锁的控制,所以在这里借用redis(单线程并且缓存操作),大概思路就是来自同一表单数据通过校验tokenid防止重复提交

1、新增表单时,在action的add()方法中生成uuid,并同时保存在redis中(有效期可为1小时),跳转到新增表单页面,在表单隐藏域中通过tokenid保存uuid,在数据并发保存时,首次进入线程的先通过tokenid拿到redis的key并进行key移除操作,进行数据的操作保存,其他重复点击的线程从redis中因得不到key,不进行任何数据处理,提示数据已经提交,勿重复操作。

并发校验唯一操作

1、在表单数据新增或修改完后,保存时往往要检查唯一性,通常是
select count(1) from table where x1=? and x2=? and x3=?,如果返回值大于0,则说明有重复,这种方式 因在保存数据时,通过sql检查数据唯一性是有延迟的,如果因校验逻辑复杂或数据量大,检验时间比如是1s,那么在0.5s中另一个用户也保存数据,那么他是在数据库中查不到刚才新增的数据的,如果这两人用同时保存一个张三客户资料,此时因上述问题保存数据,都检测不到张三存在,就存在了重复记录

2、也有人说用唯一索引不就OK了,但这种方式一方面会降低数据库性能,一方面多个参数复合检验相对不灵活(比如我要查询非停用的手机号为133的张三是否重复,而此时停用的张三可能有多个),所以不推荐使用。

3、多个用户同时操作保存这个资源时(比如张三客户资料),第一个进入的先将md5(校验唯一的多个参数)形成一个lockkey ,通过redis的setnx(lockkey, 当前时间+过期超时时间) 方式,如果返回值1,说明获取到redis锁,进行数据的保存操作,如果返回值为0说明该资源已经有用户进行保存操作,可提示用户:”系统资源正忙,请稍侯重试“,这样就避免了唯一约束的资源重复录入。(这里注意如果有效时间不设置的话,可能lockkey会因网络原因,没有释放掉,造成死锁)

那么这和幂等性有什么关系?

4、幂等性指的是无论操作多少次结果都一样,即f(f(x))=f(x) ,而我们做并发操作时其实也就是在实现幂等性操作,也就是说不论做多少次操作,都能保证结果都是一样的,换言之,也就是说在并发开发时,一定要找到可控的数据永久不变的那个点即锁,那么在这个切入点之后的操作都为无效操作,从而保证结果一致。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值