标题叫2+3,其实就这这一章的后两部分,讲了复制的另外两种形式:多主复制与无主复制。
实际上,我认为只有两种明显的关系,leader与leader之间,leader与follower之间。这两种关系间有不同的问题。而多主复制这一种情况其实是他们的复合,并没有带来新的问题。
实际上问题也只有两大类:故障了怎么办?冲突了怎么办?
回答很简单:故障时要高可用,冲突了要能一致。
多主复制
场景运维多数据中心
只有一个主库的时候,所有写入都要进过主库,主库的单点风险就非常大.
多数据中心时,用户选择更近的数据中心,可以获得更低的传输延迟
离线操作
例如我们手机上的应用,不论是否有互联网,都应该能提供查询/创建/修改功能,而再次上线时,与服务器和其他设备同步数据.
这个场景下,可以认为是网络极端不可靠情况.
优势
性能
单主配置舍近求远使用更远的网络,且受到单点吞吐量限制。
多主配置中,写操作先在本地进行处理,再与其他数据中心异步复制
利用本地网络
提升吞吐量
容忍单点故障
单个数据中心发生故障时,不影响其他数据中心写入.
容忍网络问题
多个数据中心时,不同数据中心间的网络往往不如本地网络可靠.
多主复制可以在断网后依然可以更新数据
处理写入冲突
写入冲突是多主复制最大的问题,需要解决冲突的机制
同步化
在单主数据库中,第二个写入将被阻塞。等待第一个写入完成后执行,或者直接提示用户重试。
实质上,在多主环境下,这是很难做到的。如果你需要同步的冲突检测,不如使用单主复制。如果需要异步冲突检测,要求用户解决冲突可能为时已晚。
避免冲突
确保特定记录写入同一个主库,那么冲突就不会发生。
由于许多冲突处理的实现都很差,作者推荐这一种形式。
这种方法的问题在于,如果出现写入的主库故障或者地理位置变更(因为通常以地理位置来确认写入哪个主库),需要迁移到另一个主库的情况下,冲突避免将会失效。
冲突合并
单主数据库按顺序应用写操作,最后一个写操作将确定字段的最终值。
多主环境下,两个主库以不同的顺序看到写入,需要收敛convergent至一个相同的最终值
实现冲突合并有多种途径:
写入优先级:给每个写入一个唯一ID(例如时间戳,长随机数,UUID,哈希等),挑选最高ID的写入为最终结果,并丢弃其他写入。
如果采用时间戳,则被称为最后写入胜利Last Write Wins。很流行但是容易造成数据丢失,将在本章末尾更详尽的讨论。
全区唯一ID生成器是一个不错的解决方案。
主库优先级:为每个副本分配一个唯一ID,ID编号更高的写入具有更高优先级,这也意味着数据丢失。
合并值:以某种方式将值合并在一起 - 例如,连接在一起。 我认为这本质也是将问题抛给应用层。
将问题抛给应用层:在保留所有信息的显示数据结构中记录冲突,并编写解决冲突的应用程序代码
应用层解决
在应用层解决冲突可能是最合适的,下面介绍几个解决的逻辑
写时执行
数据库系统检测到冲突时,调用冲突处理程序。
读时执行
检测到冲突时,所有冲突都被存储下来。
下次读取数据时,将多个版本的数据返回给应用程序。
应用程序可以提示用户或自动解决冲突,并将结果写回数据库。
未来的自动冲突解决
有几个对于自动解决由于数据修改引起的冲突值得一提:
无冲突复制数据类型Conflict-free replicated datatypes(CRDT):可以由多个用户同时编辑的集合,映射,有序列表等。基于双向合并,以合理的方式自动解决冲突。
可合并的持久数据类型Mergeable persistent data structures:显式跟踪历史记录,使用三向合并(我的修改,你的修改,我们的基础)。
可执行的转化operational transformation:为可同时编辑项目的有序列表而设计,与使用到了这种冲突解决方法。
什么是冲突?
典型的冲突是两个写操作并发的修改了同一条记录的同一个字段,并设为两个不同的值。但有许多更为微妙的冲突形式,作者举了一个例子。
在接下来的章节将会更深入的讨论这个问题。第七章事务中将有到更多的冲突示例,第十二章数据系统的未来将讨论用于检测与解决复制系统中冲突的可扩展方法。
多主复制拓扑
当有多个主库的时候,会有多种拓扑结构以传播写入信息。
最流行的几种事:
全拓扑
每个节点与每个节点同步写入。
环形拓扑
每个节点与一个节点同步写入,构成一个环。
星型拓扑
指定一个根节点,所有其他节点与根节点同步写入。
为了防止无限复制循环,每个节点被赋予一个唯一的标识符,并且在复制日志中,每个写入都被标记了所有已经通过的节点的标识符。消息重复通过时将被忽略。
环形拓扑与星型拓扑的典型问题是,如果单点发生故障,将中断其他节点之间的复制消息流。更密集连接的拓扑结构的容错性将更好。
全拓扑也可能有问题,因为网络不是均匀的,一些复制消息可能超过其他复制消息,如下图所示。
这是个因果关系问题,类似于前文一致前缀读的问题。因为时钟不可能被充分的同步,所以不能仅靠添加时间戳来解决这个问题。(见第八章分布式系统的麻烦)
的数据中心使用到了内置的原子钟,它们的时间可能是充分同步的。
要正确的排序这些事件,可以使用一种称为版本向量version vectors的技术,将在无主复制中被讨论。
无主复制
场景
无主复制直接放弃了主库的概念,允许任何副本直接接受来自客户端的写入。
最早的复制数据系统就是无领导的,但是在关系型数据库主导的时代,这个想法几乎已经被忘却。
在将其用于其内部的系统后,它再次成为了一种数据库架构的时尚,所以又被称为。
领取专属 10元无门槛券
私享最新 技术干货