知识卡片
复制拓扑结构在容错性与消息乱序间的权衡
内容
超过两个主库时,写入从一个节点传播到另一个节点的路径(复制拓扑)有多种设计。环形 拓扑(MySQL默认支持):每个节点只接收上一个节点的写入,加上自己的写入后转发给 下一个节点;星形拓扑:一个指定的根节点把写入转发给其余所有节点(可推广成树形); 全部到全部拓扑:每个主库直接把写入发给其他每一个主库。环形和星形的问题在于写入 可能要经过多个中间节点才能到达所有副本(需要节点转发收到的变更,为防止无限循环, 每次写入要标记已经过的节点ID),而且只要有一个节点出故障,就可能切断其余节点之间 的复制消息流、导致它们互相失联直到该节点修好——虽然可以重新配置拓扑来绕开故障 节点,但这种重配置在多数部署里需要人工介入。密集连接的全部到全部拓扑容错性更好, 因为消息能沿不同路径传播、不受制于单个节点。但全部到全部也有自己的问题:不同网络 链路的速度可能不同(比如网络拥塞导致的差异),导致某些复制消息”超过”了另一些—— 比如客户端A在主库1插入一行,客户端B随后在主库3更新这行,但主库2可能先收到更新 (此时它看来是在更新一行不存在的数据)、后收到插入,顺序反了。这本质是[[复制延迟 催生的三种一致性异常读己之写单调读一致前缀读]]里”一致前缀读”问题的变体,光靠给每次 写入加时间戳解决不了,因为节点间时钟不可能精确同步到足以在主库2正确排序这些事件; 真正需要的是版本向量这类因果排序技术,但现实中许多多主复制系统在这方面做得并不 到位(如PostgreSQL BDR当时不提供写入因果排序,Tungsten Replicator甚至不尝试检测 冲突),使用前需要仔细阅读文档并充分测试。
结构图:
flowchart LR
A[环形拓扑] -->|经多节点转发才达全部副本| A1[单节点故障切断消息流]
B[星形拓扑] -->|根节点转发给其余节点| B1[单节点故障切断消息流]
C[全部到全部拓扑] -->|每主库直连每主库| C1[容错性更好: 消息可走不同路径]
C1 -.链路速度不一, 消息可能乱序到达.-> C2[需要版本向量做因果排序]
参考来源
- 位置:《数据密集型应用系统设计》第五章《复制》"多主复制拓扑"(源文件:
_epub-src/ch5_split_003.html)
- 结论依据:原文说明环形和星形拓扑下单节点故障会切断复制消息流、需要人工重新
配置,全部到全部拓扑容错性更好但存在链路速度不一导致复制消息乱序到达的问题,
需要版本向量做因果排序而不能仅靠时间戳,直接支撑本卡片的结构梳理。
- 原始内容:循环和星型拓扑的问题是,如果只有一个节点发生故障,则可能会中断其他
节点之间的复制消息流……更密集连接的拓扑结构(例如全部到全部)的容错性更好……
一些网络链接可能比其他网络链接更快……结果是一些复制消息可能"超过"其他复制
消息……要正确排序这些事件,可以使用一种称为版本向量的技术。