V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
daocloud
V2EX  ›  程序员

3 分钟学习微服务系列 | 事务及分布式事务

  •  
  •   daocloud ·
    DaoCloud · 2017-03-08 17:13:42 +08:00 · 2360 次点击
    这是一个创建于 2823 天前的主题,其中的信息可能已经有所发展或是发生改变。

    微服务在业界正获得越来越多的关注,理解微服务架构模式,对现有企业应用转型升级大有帮助。如何快速学习微服务中复杂的概念,掌握其实践,成为众多学习者关注的问题。DaoCloud 首席架构师王天青为大家带来「 3 分钟学习微服务」系列,为微服务学习 划 重 点 !本期重点:「事务」及「分布式事务」。

    事务

    事务是现代数据库理论中的核心概念之一。如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行,我们称该事务被提交( Commit )。由于其中的一部分或多步执行失败,导致没有步骤被提交,则事务必须回滚( Rollback )到最初的系统状态。

    事务的特征

    事务是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。

    ACID

    • 原子性 (Atomicity) :事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。

    • 一致性 (Consistency ):事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

    • 隔离性 (Isolation ):一个事务的执行不能被其他事务干扰。

    • 持续性 /永久性 (Durability ):一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

    分布式事务

    Use Case

    A 账号向 B 账号汇钱

    Solution

    本地事务

    • 事务开始
    • 从 A 帐号中把余额读出来。
    • 对 A 帐号做减法操作。
    • 把结果写回 A 帐号中。
    • 从 B 帐号中把余额读出来。
    • 对 B 帐号做加法操作。
    • 把结果写回 B 帐号中
    • 事务结束

    如果跨行转账呢?

    在分布式系统中,每个节点虽然可以知晓自己的操作时成功或者失败,却无法知道其他节点的操作的成功或失败。

    当一个事务跨越多个节点时,为了保持事务的 ACID 特性,需要引入一个作为协调者的组件来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交(比如将更新后的数据写入磁盘等)。

    两阶段提交

    第一阶段 | Vote

    • 协调者会问所有的参与者结点,是否可以执行提交操作。

    • 各个参与者开始事务执行的准备工作:如:为资源上锁,预留资源,写 undo/redo log ……

    • 参与者响应协调者,如果事务的准备工作成功,则回应“可以提交”,否则回应“拒绝提交”。

    第二阶段 | Decision

    • 如果所有的参与者都回应“可以提交”,那么,协调者向所有的参与者发送“正式提交”的命令。参与者完成正式提交,并释放所有资源,然后回应“完成”,协调者收集各结点的“完成”回应后结束这个 Global Transaction 。

    • 如果有一个参与者回应“拒绝提交”,那么,协调者向所有的参与者发送“回滚操作”,并释放所有资源,然后回应“回滚完成”,协调者收集各结点的“回滚”回应后,取消这个 Global Transaction 。

    二阶段提交问题

    1. 同步阻塞操作,必然会非常大地影响性能。
    2. 另外是超时问题,比如,
    1. 如果第一阶段中,参与者没有收到询问请求,或是参与者的回应没有到达协调者。那么,需要协调者做超时处理,一旦超时,可以当作失败,也可以重试。

    2. 如果第二阶段中,正式提交发出后,如果有的参与者没有收到,或是参与者提交 /回滚后的确认信息没有返回,一旦参与者的回应超时,要么重试,要么把那个参与者标记为问题结点剔除整个集群,这样可以保证服务结点都是数据一致性的。

    3. 糟糕的情况是,第二阶段中,如果参与者收不到协调者的 commit/fallback 指令,参与者将处于“状态未知”阶段,参与者完全不知道要怎么办,比如:如果所有的参与者完成第一阶段的回复后(可能全部 yes ,可能全部 no ,可能部分 yes 部分 no ),如果协调者在这个时候挂掉了。那么所有的结点完全不知道怎么办(问别的参与者都不行)。为了一致性,要么死等协调者,要么重发第一阶段的 yes/no 命令。

    三阶段提交

    • 三阶段提交把二阶段提交的第一个段 break 成了两段:询问,然后再锁资源和最后真正提交。

    • 三段提交的核心理念是:在询问的时候并不锁定资源,除非所有人都同意了,才开始锁资源。

    作者介绍

    王天青, DaoCloud 首席架构师,曾先后在麻袋理财担任职首席架构师, EMC 中国研究院任职主任工程师,工作十多年间,做过前端,做过后端, 对云计算有深入了解。目前对云原生应用之微服务架构及敏捷的基础架构( Docker )有比较多的研究和实践,同时对大型网站的技术架构有比较多的认识和实践,在 DaoCloud 负责企业客户应用微服务架构转型。

    4 条回复    2017-03-10 00:36:14 +08:00
    ryd994
        1
    ryd994  
       2017-03-09 01:02:47 +08:00 via Android   ❤️ 1
    实际上三阶段存在一种 corner case :
    如果 coordinator 和一部分 follower 一起挂了,或者 coordinator 也会 commit
    那么剩下的 follower 就无法决定了
    如果挂了的 follower 投了拒绝,按定义其他人应该都拒绝
    如果挂了的 follower 投了通过,那就有可能 coordinator 已经收齐了所有票,告诉挂了的 follower 提交,却没来得及通知活着的 follower 。按定义,只要有一人提交,所有其他人必须提交。

    所以还有 4PC

    实际上同时挂的可能性不大,所以还是 3PC 。如果有其他途径检测挂了的 follower 是否 commit 过,也没有问题。如果 followers 复活时是无状态的,也没有问题。
    ryd994
        2
    ryd994  
       2017-03-09 01:04:19 +08:00 via Android   ❤️ 1
    3PC 实际应用很多,不过需要同步分布式系统。如果延迟波动很大,则不一定适用,要看情况分析。
    ihuotui
        3
    ihuotui  
       2017-03-09 08:49:45 +08:00 via iPhone   ❤️ 1
    其实微服务架构中已经不推荐分布式事务,采用最终一致还有定时对账
    ryd994
        4
    ryd994  
       2017-03-10 00:36:14 +08:00 via Android
    傻了,我好像说错了,我说的是 2PC 的问题
    解决就是 3PC
    惭愧惭愧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2637 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 02:00 · PVG 10:00 · LAX 18:00 · JFK 21:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.