`

软件系统的幂等性控制

 
阅读更多

什么是幂等性

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

幂等性设计

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

举个实际应用场景:用户A在网页上发起一笔游戏充值请求,浏览器引导用户去银行支付,支付成功后系统给用户进行充值。
协议设计上,我们通过全局唯一的充值订单号贯穿整个业务流程,使该业务支持幂等。
应用实现上,我们列举在银行支付成功后回调系统,进行充值的步骤进行说明。
 
[plain] view plain copy
 
  1. func pay_notify(orderid,value,state){//有问题的实现  
  2.          order = db.query("select * from payorder where orderid=$orderid");  
  3.          check(order,orderid,value,state);//判断支付金额是否与订单金额一致,判断是否是支付成功回调。  
  4.          if(order.state=='未支付'){  
  5.             db.update("update payorder set state='已支付' where orderid=$orderid");  
  6.             charge(order.username,value);//执行充值  
  7.          }else{  
  8.          return result("订单已处理")//返回订单已处理,或者返回处理成功  
  9.         }  
  10.     }  
上述实现的问题在于,当回调出现并发时,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充值这个函数,可能在另一个进程中,那么整个业务的链路就会更长,可能回调成功了,但是充值失败。同理,只要充值接口保证幂等性,对于已经回调过但是充值结果未返回的请求,回调接收程序,应当重复发起充值请求。更深入更复杂的应用场景,在数据一致性中再细讲。
 

总结

业务层设计协议时,要求请求方定义不重复的业务流水号。应用实现时,利用数据库乐观锁、插入unique key的日志等方式保证并发时的幂等。
幂等性把关环节,在协议设计评审中,评审重要业务RPC或者http接口是否支持幂等,代码评审中,重点把关请求并发时,是否仍旧能够保证幂等性。设计人员和具体实现人员在实现过程中,也应该时刻自审幂等性的实现是否过关。
-----------------------------------------------------
补充:
为啥要做幂等呢?
原因很简单,在系统调用没有达到期望的结果后,会重试。那重试就会面临问题,重试之后不能给业务逻辑带来影响,例如创建订单,第一次调用超时了,但是调用的系统不知道超时了是成功了还是失败了,然后他就重试,但是实际上第一次调用订单创建是成功了的,这时候重试了,显然不能再创建订单了。
查询
查询的API,可以说是天然的幂等性,因为你查询一次和查询两次,对于系统来讲,没有任何数据的变更,所以,查询一次和查询多次一样的。
删除数据
删除数据,仅仅第一次删除是真正的操作数据,第二次甚至第三次删除,直接返回成功,这样保证了幂等。
MVCC方案
多版本并发控制(Multiversion concurrency control,MVCC)。人们一般把基于锁的并发控制机称成为悲观机制,而把MVCC等机制称为乐观机制。这是因为锁机制是一种预防性的,读会阻塞写,写也会阻塞读,当锁定粒度较大,时间较长是并发性能就不会太好;而MVCC是一种后验性的,读不阻塞写,写也不阻塞读,等到提交的时候才检验是否有冲突,由于没有锁,所以读写不会相互阻塞,从而大大提升了并发性能。
MVCC的一种简单实现是基于CAS(Compare-and-swap)思想的有条件更新(Conditional Update)。这也是在系统设计的时候,合理的选择乐观锁,通过version或者其他条件,来做乐观锁,这样保证更新即使在并发的情况下,也不会有太大的问题。例如update table_xxx set name=#name#,version=version+1 where version=#version# ,或者是 update table_xxx set quality=quality-#subQuality# where quality-#subQuality# >= 0 。
 单独的去重表
如果涉及到的去重的地方特别多,例如ERP系统中有各种各样的业务单据,每一种业务单据都需要去重,这时候,可以单独搞一张去重表,在插入数据的时候,插入去重表,利用数据库的唯一索引特性,保证唯一的逻辑。
 
插入数据的唯一索引
插入数据的唯一性,可以通过业务主键来进行约束,例如一个特定的业务场景,三个字段肯定确定唯一性,那么,可以在数据库表添加唯一索引来进行标示。
 
API层面的幂等
这里有一个场景,API层面的幂等,例如提交数据,如何控制重复提交,这里可以在提交数据的form表单或者客户端软件,增加一个唯一标示,然后服务端,根据这个UUID来进行去重,这样就能比较好的做到API层面的唯一标示。
 
状态机幂等
在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机,就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,这时候,如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。
 
分布式锁
还是拿插入数据的例子,如果是分布式系统,构建唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁,通过第三方的系统,在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁,这样其实是把多线程并发的锁的思路,引入多多个系统,也就是分布式系统中得解决思路。
分享到:
评论

相关推荐

    UNIX 高级教程系统技术内幕

    9.12.5 保证文件系统的一致性 9.13 小结 9.14 练习 9.15 参考文献 第10 章 分布式文件系统(255) 10.1 简介 1O.2 分布式文件系统的一般特征 10.2.1 设计考虑 10.3 网络文件系统(NFS) 10.3.1 用户透视 10.3.2 设计日标...

    Minitab 15 3264位免安装便携版.7z

    该软件包括: 基础和高级统计、回归和方差分析、时间序列、演示质量的图表 模拟和分布、灵活的数据导入、导出和操纵、SPC (Statistical Process Control - 统计过程控制)、DOE (Design of Experiments - 试验设计)、...

    网络安全知识点.doc

    从网络运行和管理者角度说,他们希望对本地网络信息的访问、读 写等操作受到保护和控制,避免出现 陷门 、病毒、拒绝服务和网络 资源非常占用和非常控制等威胁,制止和防御网络黑客的攻击。对 安全保密部门来说,...

    软件测试规范

    软件测试规范 目 录 一.概述 ............................................................................................................................................................ 1 二 软件...

    最新网络安全课后习题.doc

    B A A 无意威胁和故意威胁 B 人为和自然环境 C 主动攻击和被动攻击 D软件系统和硬件系统 A 无意威胁和故意威胁 B 人为和日然环境 C 主动攻击和被动攻击 D 软件系统和硬件系统 9 网络安全包括(1)()安全运行和(2...

    电子设计-浮点频率计.docx

    系统设计采用Multisim软件仿真和硬件调试相结合的方式,最终实现了浮点频率计的设计。该系统工作稳定,性能达到了预期指标,具有一定的可行性。 关键词:频率;Multisim;分频器 1.引言 电子设计-浮点频率计全文共...

    Minitab.20.3.rar

    基础和高级统计 回归和方差分析 时间序列 演示质量的图表 模拟和分布 灵活的数据导入、导出和操纵 SPC (Statistical Process Control - 统计过程控制) DOE (Design of Experiments - 试验设计) 可靠性分析 ...

    基于AT89S52 单片的频率计

    系统,和汇编相比,C 在功能上、结构性、可读性、可维护性上有明显的优 势,因而易学易用。 Keil c51 软件提供丰富的库函数和功能强大的集成开发调试工具,全 Windows 界面。另外重要的一点,只要看一下编译后生成的...

    javaScript函数式编程

    7.1.5 纯度和幂等性129 7.2 不变性130 7.2.1 如果一棵树倒在树林里,有没有声音?132 7.2.2 不变性与递归133 7.2.3 冻结和克隆134 7.2.4 在函数级别上观察不变性136 7.2.5 观察对象的不变性137 7.2.6 对象往往是一个...

    计算机基础教学设计.doc

    (电子管的信号开关及信号放 大) 教师活动:板书计算机的组成:硬件系统和软件系统。 学生活动:分组讨论并根据计算机硬件结构对各种硬件进行分类。 教师活动:抽选三个小组进行课堂提问。最后总结归纳: 输入设备...

    (完整版)matlab毕业课程设计-图像处理.doc

    MATLAB强大的扩展功能为各个领域的应用提供了基础,由各个领域的专家相继给出了MA TLAB工具箱,其中主要有信号处理,控制系统,神经网络,图像处助,鲁棒控制, 非线性系统控制设计,最优化,小波,通信等工具箱,...

    操作系统(内存管理)

    在对内存块进行了 free 调用之后,我们需要做的是诸如将它们标记为未被使用的等事情,并且,在调用 malloc 时,我们要能够定位未被使用的内存块。因此, malloc 返回的每块内存的起始处首先要有这个结构: 清单 3...

    语言程序设计课后习题答案

    C++是一个更好的C,它保持了C的简洁、高效、接近汇编语言、具有良好的可读性和可移植性等特点,对C的类型系统进行了改革和扩充,因此C++比C更安全,C++的编译系统能检查出更多的类型错误。 C++语言最重要的特点是...

    网络安全应急预案(10).doc

    (1)I级(特别重大):造成网络与信息系统发生大规模瘫痪,事态的发展超出区一级 相关主管部门的控制能力,对国家安全、社会秩序、公共利益造成特别严重损害的突发 事件。 (2)II级(重大):造成网站或其它上一...

    unity机器人仿真-SimulinkSimscapeMultibody机器人仿真(一).pdf

    然后通信控制gazebo中机器⼈(笔者嫌⿇烦所以⽤了两台电脑,其实⼀台也可以,可以⽤虚拟机,或者 win10的linux⼦系统,⾄于linux上装matlab,我就不是很清楚了),以此来进⾏运动控制。但经过两个⽉的gazebo后,...

    epson机器人编程范例-SimulinkSimscapeMultibody机器人仿真(一).pdf

    然后通信控制gazebo中机器⼈(笔者嫌⿇烦所以⽤了两台电脑,其实⼀台也可以,可以⽤虚拟机,或者 win10的linux⼦系统,⾄于linux上装matlab,我就不是很清楚了),以此来进⾏运动控制。但经过两个⽉的gazebo后,...

    网络安全防护措施.doc

    进行 系统自身的脆弱性检查的主要目的是先于入侵者发现漏洞并及时弥补,从而进行安全防 护。由于网络是动态变化的:网络结构 不断发生变化、主机软件不断更新和增添;所以,我们必须经常利用网络漏洞扫描器对 网络...

    C程序范例宝典(基础代码详解)

    本书全面介绍了应用C语言进行开发的各种技术和技巧,全书共分12章,内容包括基础知识、指针、数据结构、算法、数学应用、文件操作、库函数应用、图形图像、系统调用、加解密与安全性、游戏、综合应用等。全书共提供...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。  拉里•埃里森  就业前景 从就业与择业的...

Global site tag (gtag.js) - Google Analytics