分布式环境中,实现幂等性,应分为两个阶段来看。
第一阶段:前台用户发起请求时刷新页面多次提交。
第二阶段:分布式系统,主业务流通完成后,从业务获取消息执行时判断幂等。
从业务由于各种原因,未返回成功标志到主业务中。主业务重复发请求到从业务,重复执行。
解决方案:
第一阶段:通过前台防止多次提交方案解决。
前台造成的多次提交,后台无法解决。
第二阶段:简单实现,主业务每次执行生成一个序列号。
从业务每次执行时,在一个事务中,先for update 通过主键查询主要操作的对象,然后查询序列号,判断是否存在。
不存在,则在从业务执行完后把序列号存到消息表中。
存在,则返回 执行成功。
先for update 通过主键查询主要操作的对象的目的。
防止第一次从业务执行完成,准备插入序列号提交时。
第二次请求,查询序列号不存在,重复执行。
一、幂等性的概念
幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。
在编程中.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。复杂的操作幂等保证是利用唯一交易号(流水号)实现.【百度百科】
数学中的幂等是指一个数对自己进行函数运算,其结果等于他自己。数学表达式为(f(x)) = f(x):也就是某个函数或者某个接口使用相同参数调用一次或者无限次,其造成的后果是一样的。
在业务层面上来说,由于我们是提供接口的一方供他人调用,别人在调用时完全可以发送无数笔相同的数据(由于bug之类)调用你的接口,这样你在提供服务的时候,必须进行幂等性运算来控制重复的申请。
实际上TCP传输协议是支持幂等的,他使用了一个唯一的序列号作为标示来保证数据的幂等性。我们在进行应用层面上的幂等性验证的时候也是同理,需要使用一个唯一的序列号进行验证,通常是我们与对接方约定的流水号来进行控制,其特点是唯一性。
二、幂等性的验证实验
在网上保证接口幂等的方法很多,最简单常用的方法时,select+insert 先查询有没有此笔数据,然后再进行数据变更操作,但是这种方法很明显效率比较低下,在高并发的程序中不建议使用。然后比较多的就是乐观锁和悲观锁,悲观锁的原理是使用select for update的形式,这种方式要求你select的条件必须是主键或者唯一索引,否则会导致锁表,在你更新时任何人做不了表格操作。乐观锁是只在更新的一瞬间进行锁表,效率上要高很多,但要通过辅助的状态参数来进行验证,如:
update table set name=’name’,version=version+1 where version=version
由于进行更新的时候会使其版本+1如果是并发的两条信息同时对表格操作时,第二笔就会因为版本号不对更新失败,这样也能保证幂等性。当然,你使用其他状态进行控制也是可行的,如果可以最好加上唯一索引,能够大幅度提高效率。
正常与其他机构进行交互的时候,往往对方会提供流水号并且保证流水号唯一,这样作为己方就可以使用数据来源+对方提供的流水号作为唯一索引来进行幂等性校验。