点击上方小坤探游架构笔记可以订阅哦
今天我们继续来聊聊单值对象在多主复制模型部署架构中的冲突问题. 因篇幅较多, 我们拆分为多篇展开, 本文不具体展开冲突的解决方案, 留着后续展开.
多主复制冲突问题
我们知道, 用户持有一份自己的name于系统中, 仅有当前用户持有对自己name的所有权, 其他用户可能最多仅具备读取权利但没有写入的权利, 对于这类数据我们称之为私有数据. 同时为方便我们更好的理解, 我们不对这份数据施加任何约束, 也就是允许用户任意写入自己想要的信息.
那么私有数据在多副本是如何表现的呢? 首先我们先看Multi-Leader复制模型下的部署架构, 这个时候UserA依次发起一系列的写入操作, 如write x = 1, x = 2, x = 3. 可以看到这里的写入操作我们从UserA的角度来看是具备前后事件的依赖关系, 也就是写入先有 1 再有 2, 先有2 再有 3, 并且将UserA 的三个操作映射到时间序列上是具备全序关系, 这个就是我们所谓的因果关系, 关注的是事件操作先后顺序, 如下:

如果上述三个操作放在单主复制模型的部署架构中, 那么由于操作发起者都是同一个UserA并在时间序列上就具备顺序性, 这种顺序性体现上述三个操作事件之间的因果关系, 于是我们就不存在所谓的冲突问题. 但是如果是放在多主复制模型的部署架构中就会存在问题, 依次写入但都路由到不同的IDC中, 如下:

这个时候我们会发现在进行异步数据复制的时候就会发现同一个字段产生了不同的数据值, 这个就是我们所谓的数据值冲突.
如前分析到, 如果这三个操作事件具备前后依赖关系, 那么我们就需要为这三个操作事件施加顺序性来维护事件之间的依赖关系, 这种方式我们在分布式系统中会称之为全局时钟, 可以是逻辑时钟或者是利用Google TureTime API机制, 关注点是事件; 如果这三个操作没有任何前后依赖关系, 那么就是并发操作关系, 这个时候我们看到在复制过程中同一个对象持有不同数据值, 这个时候我们就会称之冲突, 那么解决冲突的方式也是要具备递增的顺序性, 这个时候用于解决并发冲突问题引入的全局顺序我们会称之为版本, 其关注点是数据值.
但是仅仅全序在有些场景还不够, 比如是具备唯一性约束的name, 那么其在Multi-Leader复制模型的部署架构中, 其关注点是数据值冲突, 它要求我们在接收用户请求层面面临数据值冲突的时候要进行决策, 如下所示:

共享且仅能被覆盖一次的数据其实也与上述唯一性约束的数据相似, 但是区别在于数据持有的所有权不同, 如下:

此外还有一个很重要的因素, 前者我们无法预测资源, 后者由于是共享资源, 这类资源一般是系统提供, 因此系统对这类资源分布是可预测, 因此除了考虑上述的解决方式之外, 由于我们对资源是具备可预测的, 因此可以提前分配和设计来避免引入更为复杂度的问题, 比如上述的广播实现是一个多轮共识问题, 但是对于内部资源, 比如预订会议室这类共享资源, 我们会提前为系统资源建立一份资源占用的全局表, 利用全局表来间接帮助我们实现广播机制, 这个时候我们共享且仅被覆盖的一次数据值方式就演变为如下方式:

我们会发现都是面向用户请求层面的冲突, 这种情况下单纯引入全序关系是无法解决的,正如我们在前面讲述一个Lamport Timestamp例子, 其他节点无法感知到, 因此需要具备一个广播机制, 即全序广播.
最后一种数据类型是共享数据且能够被多次覆盖的场景, 这个时候在Multi-Leader复制模型的部署架构下, 其产生的冲突方式主要是复制过程中的冲突问题, 这个时候我们来看下:

这里还是举上一篇的例子,多人文档协同编辑场景,在这个场景下不同User都可以对同一个共享资源进行编辑修改并保存,而且这种修改保存会覆盖上一次数据最新的数据。那么在这个场景下产生数据冲突不仅体现在多用户并发编辑导致的冲突,同时在多数据运营中心之间数据复制也会产生冲突.
总结
从上述多主复制模型下的冲突我们可以看到关键技术是具备顺序和版本号, 其关注点是数据值的冲突, 但是中间我们插入了一个新词, 就是Clock. 为什么要谈及这个呢?
因为我们在独享数据场景例子中, 我们看到如果三个操作事件具备因果关系, 那么它间接解决了我们的写入冲突问题, 只是我们需要注意点的是它关注的事件前后关系, 也就是引入顺序性想要解决的是事件前后依赖关系; 而我们解决冲突引入的技术我们称之为版本, 即Version.
因此当我们考虑冲突的时候, 先关注写入操作的是并发关系还是属于前后依赖的因果关系, 这也将决定我们设计的方向是Clock 还是 Version, 也将是我们后面阐述Lamport Timestamp 以及 Version Vector的基础.

你好,我是疾风先生, 主要从事互联网搜广推行业, 技术栈为java/go/python, 记录并分享个人对技术的理解与思考, 欢迎关注我的公众号, 致力于做一个有深度,有广度,有故事的工程师,欢迎成长的路上有你陪伴,关注后回复greek可添加私人微信,欢迎技术互动和交流,谢谢!