基础篇(一)幂等性

来源:互联网 发布:搜狐自媒体 seo 编辑:程序博客网 时间:2024/06/05 14:08

1、导语

我认为我是个懒惰的人,很少去写点什么东西,哪怕是看书,我也从来没有看完过一本书。我买过不少书籍,但是几乎每本书籍都没有看完三分之一,一个是因为我懒惰,其次是一本书对于我来说有效信息量可能不足20%甚至更低,我需要去筛选一些我感兴趣的或者说对我来说有用的片段,这使得我失去去翻它的兴趣。我几乎所有的能力都学习于互联网,感谢那些乐于分享自己心得的同仁。终于下定决心,自己去写一些什么东西回报一下,力求有效信息量超过60%,写一些对读者有用,读者愿意看下去的东西。

罗里吧嗦了半天,开始进入正题吧,这是我将写下的第一篇博客,幂等性。之所以开篇就写幂等性,是因为我认为幂等性是架构设计中的基础中的基础。,没法保证幂等性,咱们接下来没法谈数据一致性与事物完整性了。

2、什么是幂等性

抄用一段数学上的定义:f(f(x)) = f(x)。x被函数f作用一次和作用无限次的结果是一样的。幂等性应用在软件系统中,我把它简单定义为:某个函数或者某个接口使用相同参数调用一次或者无限次,其造成的后果是一样的,在实际应用中一般针对于接口进行幂等性设计。举个栗子,在系统中,调用方A调用系统B的接口进行用户的扣费操作时,由于网络不稳定,A重试了N次该请求,那么不管B是否接收到多少次请求,都应该保证只会扣除该用户一次费用。

3、幂等性设计

幂等性一般应用于协议设计,TCP协议支持幂等吗?答案是肯定的,在网络不稳定时,操作系统可以肆无忌惮的重发TCP报文片段。TCP协议能够保证幂等的核心在于sequence number字段,一个序列号的在较长的一段时间内均不会出现重复。对于应用层的协议设计,原理和TCP是类似的,我们需要一个不重复的序列号。再简单一点说,在一个业务流程的处理中,我们需要一个不重复的业务流水号,以保证幂等性。

举个实际应用场景:用户A在网页上发起一笔游戏充值请求,浏览器引导用户去银行支付,支付成功后系统给用户进行充值。

协议设计上,我们通过全局唯一的充值订单号贯穿整个业务流程,使该业务支持幂等。

应用实现上,我们列举在银行支付成功后回调系统,进行充值的步骤进行说明。
func pay_notify(orderid,value,state){//有问题的实现         order = db.query("select * from payorder where orderid=$orderid");         check(order,orderid,value,state);//判断支付金额是否与订单金额一致,判断是否是支付成功回调。         if(order.state=='未支付'){            db.update("update payorder set state='已支付' where orderid=$orderid");            charge(order.username,value);//执行充值         }else{         return result("订单已处理")//返回订单已处理,或者返回处理成功        }    }




上述实现的问题在于,当回调出现并发时,order.state已经是脏读了,有可能重复充值,该实现并不能100%保证幂等。
列举三种改进方式:
1、悲观锁,select for update,整个执行过程中锁定该订单对应的记录。
2、乐观锁,affectrows = db.update("update payorder set state='已支付' where orderid=$orderid and state='未支付' "),如果affectrows=1,执行充值,否则返回已处理。
3、定义notifylog表,orderid为unique key或者primary key,执行前,先insert,若insert成功则执行充值,否则返回已处理。
以上简单例子用以说明幂等性常用应用实现,在SOA化系统中,可能很多原子功能都被拆分到不同的进程里,如charge充值这个函数,可能在另一个进程中,那么整个业务的链路就会更长,可能回调成功了,但是充值失败。同理,只要充值接口保证幂等性,对于已经回调过但是充值结果未返回的请求,回调接收程序,应当重复发起充值请求。更深入更复杂的应用场景,在数据一致性中再细讲。

4、总结

业务层设计协议时,要求请求方定义不重复的业务流水号。应用实现时,利用数据库乐观锁、插入unique key的日志等方式保证并发时的幂等。
幂等性把关环节,在协议设计评审中,评审重要业务RPC或者http接口是否支持幂等,代码评审中,重点把关请求并发时,是否仍旧能够保证幂等性。设计人员和具体实现人员在实现过程中,也应该时刻自审幂等性的实现是否过关。
2 0
原创粉丝点击