博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个简单的分布式事务系统的实现(订单系统)
阅读量:5290 次
发布时间:2019-06-14

本文共 1647 字,大约阅读时间需要 5 分钟。

的方案去实现的,这样会有什么问题呢,假设如果放到一个实例里面,全部用一个单机事务去解决,这样是能比较方便的解决数据一致性问题。但是存在两个问题,一是无法进行多实例部署,用户量增长以后,无法快速应对。二是,PHP中做事务,如果PHP遇到异常,有时并不会自动终止事务,导致DB被锁住,这是第一个版本。之后,我们推出了第二个版本V2,这个版本的时候,我们已经开发好了,库存管理系统,优惠券管理系统,PHP中,已经不直接通过DB去修改库存和优惠券,而是通过接口访问的方式去请求SERVER进行修改。这个版本,实际上已经从逻辑上,把订单系统和库存管理,优惠券管理系统已经独立出来了。数据层面已经可以独立部署,不再依赖一个单机事务去实现数据一致性功能了。但这个版本虽然解决了数据分布的问题,但同时引入了一个新的问题,就是数据在订单,库存,优惠券之间无法保证一致性。举个例子:下个订单,调用库存成功,锁定优惠券失败,生成订单失败。这时候就会导致优惠券数据不一致性情况出来,未下单的优惠券也被锁住了。有同事可能会问:订单如果创建失败,那直接回滚优惠券操作,即去解锁优惠券系统即可实现数据一致性。不错,很多时候,是可以这么操作,但如果你回滚的时候,失败了呢?你是继续在这等着直到成功,还是继续等着?呵呵。。
       正是因为这样,我们开发了V3版本,去解决这个问题。
       V3版本,我们把订单系统的逻辑从PHP中抽离出来,为什么尽量不在PHP里面做这块逻辑呢?主要有两个考虑点:1、因为订单服务这块逻辑特别重要,是影响用户操作的重要逻辑,且变动少,写成一个SERVER相对容易保持稳定。2、PHP使用CI框架做事务的时候,如果事务中出现异常,可能导致事务不结束,一直死锁的问题。
       订单系统的逻辑架构大致如下:
        
 
        订单系统中,统一通过接口调用,去访问库存管理,优惠券系统,通过mysql提供的事务机制去操作数据库部分。这里有一个前提条件,即是库存管理与优惠券系统的接口均要实现可重入的特性(可参考上一篇文章“如何实现可重入接口”)。另外,还要引入一个差错控制服务,用于做一些数据不一致的事后补尝机制。差错控制可以理解为一个消息队列机制,还有一个消费者服务从队列中取出消息进行消费。我们这里采用阿里云的ONS服务做为消息队列,通过一个消费者去订单消息进行消费。
        生成订单的逻辑如下:
        1、先把生成的订单号发到差错控制服务中。(这里必须要有个延时处理的机制,延时给消费者消费消息,因为要确保后面的流程有个结果,可以延时5分钟以上)
        2、使用订单号作为库存单号去操作库存管理系统。
        A)如果失败,则使用相同订单号去进行回滚请求操作。(这里不论成功失败,均返回失败,结束流程)
        B)如果成功,继续往下执行。
        3、使用订单号去锁定优惠券系统。
        A)如果失败,尝试库存回滚操作,尝试执行解锁操作。(这里不论解锁成功失败,均返回失败,结束流程)
        B)如果成功,继续往下执行。
        4、开启事务,创建订单相关数据。
        A)如果创建失败,回滚事务,调用库存回滚操作,调用优惠券解锁操作。(不论调用成功与否,均返回失败,结束流程)
        B)如果创建成功,提交事务,返回成功。
 
        大概流程如上所述。
        另外,差错控制服务,这里也大概描述一下其工作流程。
        1、去订单库中查看该订单是否已经生成,如果已经生成,说明数据全部一致,无须做任何操作,直接消费此消息。
        2、如果发现订单未创建,则其中可能是其中某个环节失败了。
        A)使用该订单号去调用库存回滚操作。如果失败,结束流程,返回稍后重新消费,等待消息队列重试推过来。
        B)如果成功,继续往下执行,调用优惠券系统进行解琐优惠券。如果失败,则返回稍后重新消费,等待消息队列重推消息。如果成功,则消费此消息。
 
        大致思路是通过一个差错补尝机制,非实时的自动进行数据一致性修复的方法,来保证绝大多数情况下的数据一致性。

转载于:https://www.cnblogs.com/firstdream/p/6588924.html

你可能感兴趣的文章
Access Jira RESTful API by cURL
查看>>
python tkinter GUI绘制,以及点击更新显示图片
查看>>
Spark基础脚本入门实践3:Pair RDD开发
查看>>
HDU4405--Aeroplane chess(概率dp)
查看>>
RIA Test:try catch 对 Error #1009 (无法访问空对象引用的属性或方法)的处理
查看>>
python使用easyinstall安装xlrd、xlwt、pandas等功能模块的方法
查看>>
一个杯子的测试用例
查看>>
前端面试总结——http、html和浏览器篇
查看>>
CS0103: The name ‘Scripts’ does not exist in the current context解决方法
查看>>
20130330java基础学习笔记-语句_for循环嵌套练习2
查看>>
openCV(一)---将openCV框架导入iOS工程中
查看>>
Spring面试题
查看>>
窥视SP2010--第一章节--SP2010开发者路线图
查看>>
一步步学习微软InfoPath2010和SP2010--第五章节--添加逻辑和规则到表单(2)--处理验证与格式化...
查看>>
在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。...
查看>>
MVC,MVP 和 MVVM 的图示,区别
查看>>
IDEA快速实现接口快捷方式
查看>>
用默认的打开方式打开本地文件
查看>>
JavaScript-jQuery报TypeError $(...) is null错误(jQuery失效)解决办法
查看>>
C语言栈的实现
查看>>