携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情
复制的拓扑结构描述了写请求从一个节点传播到另一个节点的通信路径。若有两个主节点,如图-7,只有一个合理拓扑结构:M1必须把他所有的写同步到M2,反之亦然。当有两个以上M,各种不同拓扑都有可能。如图-8:
最普遍的拓扑是全部到全部,即图-8 (c),每个M将其写入给同步到其他所有M。
但也会使用更多受限拓扑:如MySQL仅支持环形拓扑(circular topology),其中每个节点接收来自前一个节点的写入,并将这些写入(加上自己的写入)转发给后序节点。
另一流行结构是星形形状v。一个指定的根节点将写入转发给所有其他节点。星型拓扑可推广到树。
[v] 不要与星型模式混淆,其描述了数据模型的结构,而非节点之间的通信拓扑。
3.3.1 环形、星形拓扑
写请求需通过多个节点才能到达所有副本,即中间节点需要转发从其他节点收到的数据更改。为避免无限循环,每个节点需赋予一个唯一标识符,在复制日志中的每个写请求都标记了所有已经过的节点的标识符。当某节点收到用自己的标识符标记的数据更改时,该数据更改将被忽略,避免重复转发。
问题
若某节点故障,则可能会中断其他节点之间的复制消息流,导致它们无法通信,直到节点修复。拓扑结构可重新配置为在发生故障的节点上工作,但大多数部署中,这种重新配置工作须手动。更密集连接的拓扑结构(如全部到全部)的容错性更好,因为它允许消息沿不同路径传播,避免了单点故障。
3.3.2 全部到全部拓扑
也可能有问题。特别当一些网络链接可能比其他网络链接更快(由于网络拥塞),结果一些复制消息可能“超过”其他复制消息,如图-9。
- ClientA向L1表插入一行
- ClientB在L3更新该行
然而,L2能以不同顺序接收写入:可先接收更新(从它的角度来看,是对DB中不存在的行执行更新),之后接收L1的插入日志(本该在更新日志之前到达)。
这是个因果关系问题,类似“一致前缀读”中的:更新依赖先前完成的插入,所以需确保所有节点先接收插入,再处理更新。在每次的写日志里添加一个时间戳还不够,主要因为无法确保时钟完全同步,因而无法在L2上正确排序所收到的日志。
为正确【排序日志消息】,可使用版本向量。冲突检测技术在很多主节点复制系统中实现不够完善。如PostgreSQL BDR不提供写入的因果排序,Tungsten Replicator for MySQL甚至不尝试检测冲突。