介绍下用消息队列实现分布式事务

    在OIE的时代, 上层应用开发人员总是认为数据库足够强大, 所以很多业务可以做的非常简单。 比如A转账50元给B这个过程, 只要写一个简单sql语句块就ok了。
   
    开始事务;
    A账户减去50
    B账户增加50
    提交事务。
    
    这个实现简单明了, A账户钱减少的同时B账户的钱得到增加。但是当系统规模逐步扩大的时候, 只能不断要求使用更好的硬件以及买更贵的数据库lincence。 这种系统在超过一定规模后所需要的成本是指数增长的。为了获得近乎线性的扩展能力, 好的解决方案当然是分库分表。在分库后, 这个事务就变成了一个分布式事务。不要看到多库事务就想到XA, 如果数据库是架构在廉价服务器上, XA会带来高昂的运维成本。 这里介绍一下eBay的方法,就是用消息队列实现这种分布式事务。
    首先是业务分析, 系统是否必须在A账户减少的同时增加B账户。比如延迟50ms,在极端情况下,延迟秒级, 是否是可接受的。
    其实这个延迟基本都是可接受的。 相当于资金有了一个在途的过程。支付宝就是这么干的!
    接受这个延迟后, 我们在A账户所在的数据库建立一个日志表, 在B账户所在数据库再建立一个日志表。把事务分成两个部分。
        A库:
      1  开始事务
          A账户减去50
          A日志表记录要给B账户增加50, 同时生成全局唯一交易id
          提交事务。
        
        B库:
     2   开始事务
          B账户上应用A日志表的要求(也就是给B账户增加50)。
          B日志表记录操作完成的交易id
          提交事务。
     3   更新A日志表, 标记这个交易完成。

        这里, 两个日志表其实相当于一个消息机制。 有些中间件可以完全代替这两个日志表功能。比如阿里内部使用的notify。

    我们来分析上面这个过程。因为每个事务内涉及的账户表和日志表都在同一个数据库中, 所以上述两个事务都是本地事务。
    假设步骤1完成, 2完成前中断, 那么修复程序只要扫描A日志表, 然后重新从步骤2开始做就ok。
    假设步骤2完成, 步骤3完成前中断。 那么按照上面提到的方式修复程序可能会给B账户多加了50. 所以修复程序在修复时要先在B的日志表里查询该交易id是否执行过, 如果已经执行过, 则跳过步骤2直接步骤3。

    在应用层上想办法解决规模问题, 降低对数据库的要求, 甚至能用kv系统实现的可以完全用kv系统解决; 降低对服务器可靠性的要求, 应用自动处理错误恢复,这些实质上把服务器和数据库的价值转移到了应用层。 所以每次看到一个系统大部分价值被服务器厂商和数据库厂商赚走而心存不甘的应用开发者们, 多想想办法把价值留在自己手中吧。
    
    随着云计算的发展, 更多的云服务不断推出, 大家彻底摒弃价格昂贵的小机和oracle的时代应该不远了吧。



<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(34) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值