关于幂等性设计

参考:
http://m.blog.csdn.net/chen517611641/article/details/78085801
http://825635381.iteye.com/blog/2276077


看了很多相关的文章,参考里的文章已经很全的,但如果有其他方式希望有人分享,谢谢!!
 写本文的目的是为了总结,便于自己以后复习
一。前端防重复提交:
1.js隐藏提交按钮
2.跳转到提交成功页面
3.session带标识(类似于下面的token机制)
产生页面时,服务器为每个form分配唯一标识,在form的隐藏字段中设置此标识号,并在session中保存此标识号。
当提交表单时,比较请求的唯一标识和session中的唯一标识是否一致,如果一致则进行业务处理再返回结果前

清空session中标识。


二。接口幂等
一个软件系统中,所有的接口都可以归结为增删改查四大类;下面我们对这四大类接口进行分析;
1.查询和删除
   两者具有天然幂等性:在数据不变的情况下,查询一次和查询多次结果是一样的同样删除一次和删除多

  次都是把数据删除。


2.新增业务类接口,我们要解决如下两个问题 
第一:同一个用户用同样的数据多次请求同一个接口(不管是什么原因多次提交,他应该只请求一次) 
可以通过防重复提交来解决;token机制(每次请求前先向redis申请token,数据提交给redis,
redis根据token查该请求的处理状态(是否处理过,是否成功,处理结果是什么))
第二:不同用户的提交同样的数据请求同一个接口; 
一个开放的系统,不能杜绝两个不同的客户端(用户)同时请求;但是可以交给数据的最后防线,存储层;
通过唯一索引或唯一组合索引可以防止新增数据存在脏数据 (当表存在唯一索引,并发时新增报错时,再查询一次就可以了,
数据应该已经存在了,返回结果即可) ;


3.更新业务类接口
系统中的大部分业务都可以归属到更新业务,比如:电商秒杀,禁用用户等,只要有更新操作的都归结到更新业务
更新业务类接口,不仅需要有表单防重复提交的验证,还需要有更精细的控制,以防止在高并发环境中出现脏读,
幻读等引起的错误数据更新结果
更新业务类接口幂等性解决方案一般是通过各种层面的锁和CAS机制;
1>状态机幂等 ??
在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机(状态变更图),
就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,这时候,如果状态机已经处于下一个状态,
这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。
2>分布式锁 ??
拿插入数据的例子,如果是分布是系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁,
通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁,
这样其实是把多线程并发的锁的思路,引入多多个系统,也就是分布式系统中得解决思路。 
要点:某个长流程处理过程要求不能并发执行,可以在流程执行之前根据某个标志(用户ID+后缀等)获取分布式锁,
其他流程执行时获取锁就会失败,也就是同一时间该流程只能有一个能执行成功,执行完成后,释放分布式锁(分布式锁要第三方系统提供) 
3>悲观锁
select for update,整个执行过程中锁定要操作的记录,执行完释放
4>乐观锁
基本思路是CAS
update table_xxx set num=#num_new where id=#id and num=#num_old;  
update table_xxx set num=#num_new   and version=version+1 where id=#id and version=#version; 
update table_xxx set num=num-#data where id=#id and num-#data>=0;
小知识:
update table_xxx set num=num-#data where id=#id; 非幂等
update table_xxx set num=#num_new where id=#id; 幂等(先算好结果再设置) 
5>select+insert   

根据唯一索引(各种编号)查询是否执行过,是否成功,然后在进行业务处理

6>select+update   

需要用到乐观锁技术或者CAS实现


三。数据库
1.唯一索引或组合唯一索引
当表存在唯一索引,并发报错
四。供第三方调用的数据接口
唯一索引(或者组合索引)或者token
例如:银联提供的付款接口:需要介入商户提交付款请求时附带:source(来源),seq(序列号)
source+seq在数据库里面做唯一索引,防止多次付款


测试用例
通过下面的方法可以初步验证接口幂等性的健壮性;
1.同一个请求,多次提交到同一台节点,多次提交到不同节点
2.同一个请求,同时到达同一个节点,同时到达不同节点
3.有逻辑先后顺序的消息,请求乱序的处理,比如创建订单的请求和支付订单的请求,
在不保证第一个请求先于第二个请求到达服务器;


你可能感兴趣的:(并发编程)