网易|网易分布式数据库多活架构的演进与实践( 三 )


数据库单元化场景下主要用到NDC的双向同步能力 。
网易|网易分布式数据库多活架构的演进与实践
本文插图

七、解决回环复制

双向同步第一个要解决的问题即是回环复制 。 如果对同步的数据不加过滤仍由其在不同单元的数据库中来回复制必然消耗大量的网络带宽 , 最终还会导致数据不一致 。
解决回环复制的核心是如何给每个增量变更标注其发生的机房 , 然后在同步时避免将其同步回发生的机房 , 就能解决回环复制的问题了 。 这里总结了三种解决回环复制的方案:

  • 引入额外字段:给每个同步的表加入额外字段标注上一次对其操作的机房信息 , 此方案对同步的性能影响最小 , 切可以做到跨不同数据库类型使用 , 但是对业务的表有侵入 。
  • GTID:使用MySQL自己的GTID来标注事务的机房信息 , 这也是MySQL原生复制解决回环复制的方案 , 其对同步的性能影响较小 , 完全无侵入 , 但是只能用于MySQL之间的双向同步 。
  • 事务中引入额外SQL:在业务的事务中加入额外的SQL来标注此事物产生的机房 , 此方案也能做到跨数据源 , 对业务侵入较小 , 但是对同步的性能影响较大 。
三种方案都有各自的优缺点 , 实现上根据需要选择即可 。 NDC对三种方案都做了实现 , 在单元化场景下实际选择的是方案一 , 主要是其使用的额外字段同时是另外一个功能需要的字段 , 算是重复利用 , 没有引入额外开销 。
网易|网易分布式数据库多活架构的演进与实践
本文插图

八、解决数据冲突
正常情况下 , 每个单元都写自己负责的数据 , 不存在数据冲突 , 但是当某个单元不可用 , 要做流量切换的时候 , 就会出现多个单元同时写入同一行数据的情况 , 从而产生数据冲突 。 数据冲突不可避免 , 我们需要一个机制保证产生冲突的数据最终能保证一致 。
解决数据冲突的核心思路是给每个变更赋予一个版本信息 , 当产生数据冲突时总是保留高版本的数据即可保证最终一致性 。 NDC采用了最简单的物理时间作为变更的版本信息 , 在进行数据同步时 , 只有当对端版本低于(或等于)同步的变更时 , 才同步到对端 。
网易|网易分布式数据库多活架构的演进与实践
本文插图

这样的数据冲突解决方案能解决99%以上的数据冲突 , 保证数据的最终一致 。 但是在一些特殊情况下可能失效 , 一个比较典型的例子就是机房间由于物理时间基准不一致 , 某个后发生的变更它的版本却更小 , 这样这个变更无法同步到对端机房 , 最终导致数据不一致 。
解决这个问题的办法是将这种特殊数据版本信息给提升到发生变更之前的版本 , 保证变更能同步到其他机房 。

在实践中我们发现单个机房内对同一行数据的并发修改也可能造成版本后退 , 当删除和插入操作同时进行时也可能出现版本未知的情况 , 对于这样的特殊场景都只能通过调整特殊的同步手段最终来确保数据的一致性 。
网易|网易分布式数据库多活架构的演进与实践
本文插图

九、实时数据校验
数据校验对一个数据同步系统是一个可选但又是必须的功能 。 在单元化的双向同步功能中我们不仅使用定期的全量校验发现系统中存在的不一致风险 , 还提过了实时数据校验功能更实时地发现数据不一致的风险 。 数据校验的覆盖范围和对数据库的性能影响是一个相悖的问题 , 更大的校验覆盖范围必将导致更大的数据库性能开销 。 产品上我们允许用户选择实时数据校验的范围 , 可选的范围包括: