一. 什么是幂等性
幂等(idempotent): 在编程中.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同.幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“setTrue()”函数就是一个幂等函数,无论多次执行,其结果都是一样的.更复杂的操作幂等保证是利用唯一交易号(流水号)实现.
以上概念来源于百度百科.
根据以上解释我们可以举出几个跟主题http相关的例子来帮助大家理解:
a. get 请求: 对于一个get请求来说, 理论上我们在同时并发一万次的情况下,返回的结果都是一样的, 这个请求则幂等请求
b. post 请求: 在http restful定义中, 此请求就是idempotent(幂等)的. 用来insert(), 而对于insert的结果来说, 应该只返回true/false, 所以是幂等的
c. put 请求: 用来 update(), 举个简单的例子, 如: 更新用户余额(从10到100), 有两种操作方式 1. setAmount(100), 2. addAmount(90). 应该可以很简单的知道, setAmount(100)无论多少并发同时请求,最终返回的结果都是100, 则可认为是幂等的<不考虑数据库重读与锁的情况>, 而addAmount(90), 来个10次并发, 则有可能被更新为910元, 所以这样的请求则为非幂等的.
d. delete 请求: 用来 delete(), 无论多少并发去delete一个指定条件的时候, 要么成功, 要么失败, 则认为些种方式的请求为幂等的.
根据以上举例我们可以很清楚的知道, 在系统设计中保证操作的幂等性是很重要的.
二. 为什么要使用幂等性
还是从例子开始: 假设有一个用户在ATM上取钱, 取了1000元, 这时候ATM会先向银行服务中心发出一个请求, 扣除用户账户1000元, 成功后再吐1000元给用户.
针对这个案例我们可以定义为函数:
bool withdraw($uId, 1000)
但在现实情况中, 有可能会出现, 因为网络不太好, 则会出现以下种情况:
a. atm 向银行 server 发出扣款请求, 没有成功, 这不会出现什么问题, 因为用户的钱没减少, 也没取到钱.
b. atm 向银行 server 发现扣款请求, 成功了, 但没返回给atm结果, 出现问题: 用户账户上钱少了, 用户却没取到钱. 然后atm接收结果超时后再重试一次, 这次收到返回结果了, 这时候就会出现扣款两次, 用户却只取了1次钱的结果
将上面的例子转化为流程图则为:
通过流程图我们可以清楚的看到, 在实际业务中, 无论 atm retry多少次, 用户账户上始终应该只扣除1000元.
三. 怎么使用幂等性
1. 采用分布式事务,通过引入支持分布式事务的中间件来保证withdraw功能的事务性。分布式事务的优点是对于调用者很简单,复杂性都交给了中间件来管理。缺点则是一方面架构太重量级,容易被绑在特定的中间件上,不利于异构系统的集成;另一方面分布式事务虽然能保证事务的ACID性质,而但却无法提供性能和可用性的保证。
2. 一种更轻量级的解决方案是幂等设计。
例如: 大家经常在银行或移动营业厅办理业务, 首先取个号子, 然后拿着号子去柜台办理, 办完以后就把号子丢弃. 而对柜台来说, 这个号子一旦办理过业务, 则第二次再拿此号子去办, 柜台也不会给你办. 衍生到实际设计中流程图如下:
这时大家可以清楚的看到, 在这种幂等性设计中, 会很好的保证数据的一致性.
四. 总结
理解就是总结, 哈哈.
参考地址:http://www.cnblogs.com/weidagang2046/archive/2011/06/04/2063696.html