`
aa8945163
  • 浏览: 275182 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

电商分布式系统要支持幂等性

 
阅读更多

1. 什么是幂等性

 1.1 幂等的来源

        幂等来源于数学的概念,在数学的概念里,大概分为以下两种概念:

  •         在一个二元运算下,幂等元素是指被自己重复运算(或对于函数式为复合)的结果等于他自己的元素。例如,在乘法下下唯一的两个幂等实数为0和1.即s=s*s。
  • 在一元运算为幂等的时候,其作用在任一元素两次后会和其作用一次的结果相同。例如高斯符号便是幂等的,即f(x)=f(f(x))。
1.2 在http中幂等的规范
        HTTP的幂等性指的是一次和多次请求某一个资源应该具有相同的副作用。如通过PUT接口将数据的Status置为1,无论是第一次执行还是多次执行,获取到的结果应该是相同的,即执行完成之后Status =1。

2. 接口设计是需要幂等性的

        首先看看http的幂等接口:

  • GET方法是向服务器查询,不会对系统产生副作用,具有幂等性(不代表每次请求都是相同的结果)
  • 也就是说PUT方法首先判断系统中是否有相关的记录,如果有记录则更新该记录,如果没有则新增记录。
  • DELETE方法是删除服务器上的相关记录。

下面详解说一下:

HTTP协议本身是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式: 
      一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵守了HTTP协议的各种规定; 
      另一种是SOA的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后在HTTP之上建立了自己的应用层协议。

  HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。 
      HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。 
      比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”; 
      而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的: 

  POST所对应的URI并非创建的资源本身,而是资源的接收者。 
比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子, 
      HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI; 
      所以,POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。 
      比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。

  在介绍了几种操作的语义和幂等性之后,我们来看看如何通过Web API的形式实现前面所提到的取款功能。 
      很简单,用POST /tickets来实现create_ticket;用PUT /accounts/account_id/ticket_id&amount=xxx来实现idempotent_withdraw。 
值得注意的是严格来讲amount参数不应该作为URI的一部分,真正的URI应该是/accounts/account_id/ticket_id,而amount应该放在请求的body中。这种模式可以应用于很多场合,比如:论坛网站中防止意外的重复发帖。

 

   关联接口的实际业务

        现在来一个商城支付系统的概念系统,从用户下单到支付系统白条支付、在调用户的账务;订单系统和支付系统和白条账务系统,都有流转状态。下面看看接口:

        

boolean pay(int accountid,BigDecimal amount) //用于付款,扣除用户的

 

 

       

        这种情况下,支付系统已经扣款,但是订单系统因为网络原因,没有获取到确切的结果,因此订单系统需要重试。
由上图可见,支付系统并没有做到接口的幂等性,订单系统第一次调用和第二次调用,用户分别被扣了两次钱,造成重复扣款,不符合幂等性原则(同一个订单,无论是调用了多少次,用户都只会扣款一次)。
如果需要支持幂等性,付款接口需要修改为以下接口:

 

boolean pay(int orderId,int accountId,BigDecimal amount)

        通过orderId来标定订单的唯一性,付款系统只要检测到订单已经支付过,则第二次调用不会扣款而会直接返回结果:



 

        在不同的业务中不同接口需要有不同的幂等性,特别是在分布式系统中,因为网络原因而未能得到确定的结果,往往需要支持接口幂等性。

 

3. 分布式系统接口的幂等性

        随着分布式系统以及微服务的普及,一个系统被横向和纵向切分成若干应用,部署成多台服务,这样因为网络原因、系统瓶颈、并发问题、服务器故障、超时等等原因而未获取都确切结果的,者就需要被调用的系统具有幂等性。例如上文所阐述的支付系统,针对同一个订单保证支付的幂等性,一旦订单的支付状态确定之后,以后的操作都会返回相同的结果,对用户的扣款也只会有一次。这种接口的幂等性,简化到数据层面的操作:

update userAmount set amount = amount - 'value' ,paystatus = 'paid' where orderId= 'orderid' and paystatus = 'unpay'

         其中value是用户要减少的订单,paystatus代表支付状态,paid代表已经支付,unpay代表未支付,orderid是订单号。

        在上文中提到的订单系统,订单具有自己的状态(orderStatus),订单状态存在一定的流转。订单首先有提交(0),付款中(1),付款成功(2),付款失败(3),简化之后其流转路径如图:



         
当orderStatus = 1 时,其前置状态只能是0,也就是说将orderStatus由0->1 是需要幂等性的

update Order set orderStatus = 1 where OrderId = 'orderid' and orderStatus = 0

 

        当orderStatus 处于0,1两种状态时,对订单执行0->1 的状态流转操作应该是具有幂等性的。
这时候需要在执行update操作之前检测orderStatus是否已经=1,如果已经=1则直接返回true即可。

        但是如果此时orderStatus = 2,再进行订单状态0->1 时操作就无法成功,但是幂等性是针对同一个请求的,也就是针对同一个requestid保持幂等。

这时候再执行

update Order set orderStatus = 1 where OrderId = 'orderid' and orderStatus = 0

         接口会返回失败,系统没有产生修改,如果再发一次,requestid是相同的,对系统同样没有产生修改。

 

 4. 电商系统中的应用

      电商的很多业务,考虑更多的是 BASE(即Basically Available、Soft state、和Eventually consistent),而不是 ACID(Atomicity、Consistency、Isolation和 Durability)。 
即为了满足高负载的用户访问,我们可以容忍短暂的数据不一致。

 

那怎么做呢? 

      第一,不做分布式事务,代价太大。 
      第二,不一定需要实时一致性,只需要保证最终的一致性即可。 
      第三,“通过状态机和严格的有序操作,来最大限度地降低不一致性”。 
      第四,最终一致性(Eventually Consistent)通过异步事件做到。 
      如果消息具有操作幂等性,也就是一个消息被应用多次与应用一次产生的效果是一样的话,那么把不需要同步执行的事务交给异步消息推送和订阅者集群来处理即可。假如消息处理失败,那么就消息重播,由于幂等性,应用多次也能产生正确的结果。 
      实际情况下,消息很难具有幂等性,解决方法是使用另一个表记录已经被成功应用的消息,即消息队列和消息应用状态表一起来解决问题。
PS:
      最佳结果是引入一个“第三方”的通知/消息机制,比如文中提到的ticket亦或者异步消息推送,而业界传闻很久的淘宝notify框架大概也就是以这为基石创建的吧。 
      系统越来越SOA所导致的分布式锁的问题是目前所有web开发人员面临的问题,纯粹靠程序事务以及数据库事务是无法解决的,倒是最终一致性很巧妙的解决了该问题。 
      使用同一节点事务加上消息机制可确保即使系统发生故障也可确保最终一致性,同时又保证了性能和可伸缩性。
  • 大小: 18.4 KB
  • 大小: 20.2 KB
  • 大小: 9.4 KB
分享到:
评论

相关推荐

    分布式数据库样例

    7. 数据一致性模型:分布式数据库提供了多种一致性模型,如强一致性、最终一致性、因果一致性等。不同的模型在一致性和可用性之间有不同的权衡。 8. 分布式索引:索引是提高查询效率的关键,分布式数据库需要考虑...

    蘑菇街分布式服务框架的挑战

    1. **CAP定理**:指出了分布式系统无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)三个条件。在实际应用中,通常需要在这三个条件之间做出权衡。 2. **BASE理论**:代表...

    分布式开放消息系统

    它最初是为了解决阿里巴巴内部大规模分布式系统中的消息传递问题而开发的,并在双11等大型活动期间得到了充分的验证。RocketMQ不仅支持简单的消息传递功能,还提供了一系列高级特性,包括但不限于顺序消息、消息过滤...

    电商海量订单处理OFC系统的关键技术环节

    3. **数据一致性手段**:采用防重、幂等性等技术手段,结合状态机和人工介入机制,确保数据的一致性。 #### 灰度部署 1. **部署方案**:支持按Group集群部署,支持分层部署,如接单、分布式队列引擎、业务处理系统...

    分布式数据库架构及企业实践.pdf

    3. 幂等性支持:在分布式环境中,由于网络延迟等原因可能导致请求重复发送,Mycat支持幂等性操作,保证多次执行同一操作的结果是一致的。 4. 数据读写分离:Mycat可以实现主从复制环境下的读写分离,将读操作分散到...

    seata分布式事务0.9.0

    - 大数据处理:在处理大量数据的分布式系统中,Seata可以帮助确保事务的正确性。 - 电商平台:在订单、库存、支付等多个服务协同操作时,Seata可以保证整个流程的事务一致性。 总结,Seata 0.9.0是一个强大的...

    阿里分布式数据库服务原理与实践

    4. 幂等性与事务一致性:为保证分布式环境下数据的一致性,阿里引入了幂等操作和分布式事务管理机制,如两阶段提交、三阶段提交等,确保数据操作的正确性。 三、分布式数据库服务实践 1. 弹性扩展:阿里云的分布式...

    全面解剖RocketMQ和项目实战-day3-part1.7z

    RocketMQ是中国阿里巴巴开源的一款分布式消息中间件,它在大规模分布式系统中扮演着重要的角色,用于...通过学习这些内容,开发者可以更好地理解和运用RocketMQ解决分布式系统中的复杂问题,提升系统的稳定性和可靠性。

    微服务的数据一致性分发问题解决方案.docx

    然而,这种模式也需考虑发件箱数据的清理、错误重试和消息幂等性等问题。 总结来说,微服务的数据一致性分发是一项复杂任务,需要权衡性能、实时性和一致性。事务性发件箱模式提供了一种有效的解决方案,但实施时仍...

    Java实时回单同步的代码

    9. **幂等性**:为了防止因网络重传或其他原因导致回单被重复处理,设计接口时应考虑幂等性,即多次调用同一接口,结果应该保持一致。 通过以上技术点的运用,我们可以构建出一个高效、稳定的Java实时回单同步系统...

    实时计算在点评

    幂等性是指在分布式系统中执行一个操作多次,其效果与执行一次相同。这是构建可靠分布式系统的重要原则,特别是在网络不稳定或消息可能重复的情况下。 11. 实际案例分析 实际案例,例如1号店电商在双11期间使用...

    TCC分布式事务解决方案.docx

    - **幂等性**:为避免因重试机制导致的数据不一致问题,TCC事务的Try、Confirm和Cancel接口需要具备幂等性。可以在分支事务记录表中添加事务ID作为标识,确保同一事务的多次执行结果相同。 - **悬挂**:在分布式事务...

    优惠券设计(数据库、代码)

    以上只是优惠券系统设计的一部分关键知识点,实际开发中还需考虑更多细节,如分布式系统中的幂等性、事务管理、日志记录等。一个完整的优惠券系统还需要结合前端界面,提供良好的用户体验。对于Java开发者来说,理解...

    java+redis+lua实现重复提交操作拦截.zip

    在IT行业中,尤其是在分布式系统和高并发场景下,防止重复提交是确保数据一致性的重要策略。本项目"java+redis+lua实现重复提交操作拦截"旨在解决这个问题,通过结合Java、Redis和Lua技术来构建一个高效的解决方案。...

    Java消息中间件MQ面试题(2024最新版).docx

    RocketMQ 是阿里巴巴开源的一款消息中间件,设计目标是支持大规模分布式系统中的高并发、低延迟和高可扩展性。RocketMQ 专为大规模互联网服务设计,尤其适用于电商、金融等领域的大流量场景。但它可能在小规模应用或...

    第四节课支付模块详解1

    - 微信对接:同样关注接口幂等性,确保后台系统能够处理重复请求。 5. **后台管理系统权限控制**: - 权限系统通常包括账号、角色、权限和资源管理。 - 页面权限控制用户可访问的页面,操作权限控制用户在页面上...

    Java工程师面试突击第1季笔记

    - **RocketMQ**:阿里巴巴开源,适合大规模分布式系统,尤其在电商领域。 4. **MQ的高可用** - 集群部署 - 多副本策略 - 选举机制(如Raft协议) 5. **消息的幂等性与重复消费** - 幂等性:确保同一消息被...

    使用rabbitmq解决超卖问题

    利用消息队列的特性,实现库存操作的异步处理和幂等性,确保在处理大量并发请求时,系统的稳定性和准确性得到保障。同时,结合死信队列、分布式事务以及限流策略,可以进一步优化解决方案,提高整体系统的容错能力和...

    整理流程.png.zip

    它旨在提高服务的治理效率,提升系统的可扩展性和稳定性,使得分布式系统开发更加便捷。本文将深入探讨Dubbo的核心概念、工作原理以及实际应用场景,帮助“喜欢dubbo等rpc框架的伙伴”更好地理解和运用这一强大的...

Global site tag (gtag.js) - Google Analytics