NET Core微服务之路:再谈分布式系统中一致性问题分析( 三 )

  • I: Isolation , 隔离性
  • D: Durability , 持久性
  • 回到Q2和Q3的问题上 , 使用关系型数据库可以解决这样的强一致性需求 , 然而 , 单纯通过强一致性的数据库去面对不断拆分的元组 , 是难以满足互联网高流量的需求的 , 或许你会说使用服务器固态硬盘和读写分离的模式去应对 , 但这绝对只是一个应对方案而已 。 因此 , 在拆分的时候尽量把转账的相关账户放入一个数据库分片 , 而Q3上 , 把订单和存库放入一个分片 , 因为中途不会存在任何改变 , 从0到100必须保证任何状态都是原始的初始状态 。
    但是 , 我们就Q2假设另外一个场景 , 假设账户的数量巨大 , 对账户存储进行了拆分 , 关系型数据库分为8个实例 , 每个实例8个库 , 每个库8张表 , 共512张表 , 假如转账的账户正好在一个库里 , 这个问题依赖关系型数据库的事务来保持强一致性 , 但是 , 如果两个账户在不同的库里 , 这个事务就无法封装在同一个数据库中的 , 这样就会发生一个账户扣款成功 , 而另外一个库的账户增加失败的情况 。
    这时 , 我们就需要考虑另外一种理论:CAP理论和BASE理论 , 就CAP原文可参考百科 。 而BASE原文可参考百科 。
    帽子理论证明 , 任何分布式系统同时只可满足两点 , 没法三者兼顾 。
    • C:Consistency , 一致性, 数据一致更新 , 所有数据变动都是同步的
    • A:Availability , 可用性, 好的响应性能 , 完全的可用性指的是在任何故障模型下 , 服务都会在有限的时间处理响应
    • P:Partition tolerance , 分区容错性 , 可靠性
    关系型数据库由于关系型数据库是单节点的 , 因此 , 不具有分区容错性 , 但是具有一致性和可用性 , 而分布式的服务化系统都需要满足分区容错性 , 那么我们必须在一致性和可用性中进行权衡 , 具体表现在服务化系统处理的异常请求在某一个时间段内可能是不完全的 , 但是经过自动的或者手工的补偿后 , 达到了最终的一致性 。
    NET Core微服务之路:再谈分布式系统中一致性问题分析文章插图
    而BASE理论的提出 , 解决了CAP在分布式系统中的一致性和可用性不可兼得的问题 。 “BASE”在化学单词中是指碱 , 因此我们可以想到一个词语叫“酸碱平衡” , 而在实际的场景中 , 我们可以分别使用ACID和BASE来解决分布式服务化系统的一致性问题 。 BASE理论与ACID理论完全不同 , 它满足CAP理论 , 通过牺牲强一致性而获得可用性 , 一般应用在服务化系统的应用层 , 通过达到最终一致性来尽量满足不同业务上的需求 。
    • BA:Basically Available , 基本可用
    • S:Soft State , 软状态 , 状态可以有一段时间不同步
    • E:Eventually Consistent , 最终一致 , 最终数据是一致的就可以了 , 而不是时时保持强一致

    NET Core微服务之路:再谈分布式系统中一致性问题分析文章插图
    按照BASE模型实现的系统 , 由于不保证强一致性 , 系统在处理请求的过程中 , 可以存在短暂的不一致状态 。 系统在做每一步操作的时候 , 通过记录每一个临时状态 , 在系统出现故障的时候 , 可以从这些临时状态中继续完成未完成的请求处理 , 或者回退到原始状态 , 最后达到一致的状态 。
    例如Q1的转账状态为例 , 我们把两个账户的转账情况粗分为四个状态:
    • 第一个状态为准备状态 , 用户准备向另外一个进行用户转账;
    • 第二个状态为扣额状态 , 系统将从转账用户中扣取相应余额;
    • 第三个状态为加额状态 , 系统将从收款用户中增加相应余额;
    • 第四个状态为完成状态 , 系统转账完成后的确认;
    在这过程中 , 系统需要将每一步的操作状态都进行记录 , 一旦某个环节出现故障 , 系统能够发现故障环节并继续完成未完成的任务 , 最终完成任务 , 达到一致的最终状态 。 在实际的业务生产环境中 , 通常每个阶段的状态都是通过持久化的执行任务 , 一旦出现了问题 , 定时任务会检查未完成的任务 , 继续执行未完成的任务 , 直到执行完成为止;再或者 , 该状态是属于取消状态 , 跟数据库事务执行方式一样 , 那么这个过程中已经完成的状态应该回滚到原始状态 , 整个过程还可以细化到如下更加详细实际转账流程:


    推荐阅读