一. 断言:
幂等性的数学表达:f(f(x)) = f(x)。
幂等性是系统接口对外的一种承诺。
幂等性指的是,使用相同参数对同一资源重复调用某个接口的结果与调用一次的结果相同。
幂等性的一个实现是,使你的接口必须返回 0(成功),即使这时资源或动作已经停止并且无工作要完成。
二. 电商常见问题:
2.1. 如何防范 POST 重复提交
HTTP POST 操作既不是安全的,也不是幂等的(至少在HTTP规范里没有保证)。
当我们因为反复刷新浏览器导致多次提交表单,多次发出同样的POST请求,导致远端服务器重复创建出了资源。
所以,对于电商应用来说,第一对应的后端 WebService 一定要做到幂等性,第二服务器端收到 POST 请求,
在操作成功后必须302跳转到另外一个页面,这样即使用户刷新页面,也不会重复提交表单。
2.2. 集群环境下的定时任务幂等性
分布式环境下,定时任务或异步处理如何保持幂等性?
三. 把分布式事务分解为具有幂等性的异步消息处理:
电商的很多业务,考虑更多的是 BASE(即
Basically Available、
Soft state、和
Eventually consistent),而不是 ACID(Atomicity、Consistency、Isolation和 Durability)。即为了满足高负载的用户访问,我们可以容忍短暂的数据不一致。
那怎么做呢?
第一,不做分布式事务,代价太大。
第二,不一定需要实时一致性,只需要保证最终的一致性即可。
第三,“通过状态机和严格的有序操作,来最大限度地降低不一致性”。
第四,最终一致性(Eventually Consistent)通过异步事件做到。
如果消息具有操作幂等性,也就是一个消息被应用多次与应用一次产生的效果是一样的话,那么
把不需要同步执行的事务交给异步消息推送和订阅者集群来处理即可。假如消息处理失败,那么就消息重播,由于幂等性,应用多次也能产生正确的结果。
实际情况下,消息很难具有幂等性,解决方法是使用另一个表记录已经被成功应用的消息,即消息队列和消息应用状态表一起来解决问题。
参考资源:
1)weidagang2046,博客园,
理解HTTP幂等性;
2)相关设计模式“Synchronized Token(简而言之,就是客户端的每一次 Request 里,必须携带一个服务器端给出的 Hash Code 作为 Token,这个 Token 只能用一次,不能重复使用) ”和“幂等接收器,Idempotent Receiver ”;
3)针对 POST ,请参考
HTTPLR(由Bill de hÓra提出)、
Mark Nottingham的POE(POST Once Exactly)和Paul Prescod的
HTTP中的可靠传递。(另一个值得一提的是Yaron Goland的
SOA-Rity);
4)淘宝核心系统团队博客,2010,
用消息队列和消息应用状态表来消除分布式事务