分布式数据库跨集群数据迁移,最核心的痛点不是"怎么搬",而是"搬完之后数据对不对"。很多团队花了大量精力做迁移工具、做同步链路,结果上线后才发现两边数据对不上——行数对了但字段值有偏差,或者主键没问题但关联表的外键关系断了。跨集群一致性校验,本质上就是在迁移完成后,用一套系统化的方法去验证源集群和目标集群的数据在逻辑层面、物理层面、业务层面是否完全一致。这件事做不好,轻则数据质量事故,重则业务瘫痪。下面我会从校验策略、技术实现、常见坑点三个维度,把这件事讲透。

一、为什么跨集群迁移必须做一致性校验

分布式数据库的跨集群迁移,通常涉及几种场景:机房搬迁、云上云下切换、多活架构调整、版本升级换集群等。不管哪种场景,数据从A集群搬到B集群,中间一定会经过网络传输、格式转换、分批写入等环节。每一个环节都可能引入数据不一致。

具体来说,不一致的来源主要有三个:第一是传输层丢包或乱序,导致部分数据没写进去或者写了两次;第二是数据类型转换问题,比如源端是DECIMAL(18,6),目标端精度不够被截断了;第三是并发写入时的时序问题,同一行数据被先后更新了两次,迁移只抓到了最后一次,但业务逻辑依赖的是中间状态。

所以一致性校验不是可选项,是必选项。而且不是简单跑个count(*)对比行数就完事了,那只是最粗粒度的检查。

二、一致性校验的三个层次

做跨集群校验,我建议分三层来做,从粗到细,逐步收敛问题。

第一层:数量级校验。这是最基本的,对比源和目标的表数量、每张表的总行数、每张表的总数据大小(字节数)。如果行数对不上,说明有数据丢失或重复。这一步可以用简单的SQL批量跑:

-- 源集群
SELECT table_name, table_rows 
FROM information_schema.tables 
WHERE table_schema = 'your_db';

-- 目标集群执行同样的查询,然后做diff

但要注意,table_rows在InnoDB里是估算值,不是精确值。精确行数需要用SELECT COUNT(*)或者借助分布式计数框架。对于超大表,COUNT(*)本身也很慢,可以用近似算法如HyperLogLog来做快速估算对比。

第二层:内容级校验。行数对了不代表数据对了。这一层要做的是逐行或者抽样比对字段值。常用方法有三种:

第一种是基于checksum的校验。对每一行数据计算一个哈希值(比如MD5或者CRC32),源和目标分别算,然后对比。MySQL自带的CHECKSUM TABLE可以用,但它是表级别的,粒度不够细。更好的做法是自己写一个按主键分片的校验任务:

-- 源端按主键范围分批计算checksum
SELECT MIN(id), MAX(id), 
       BIT_XOR(CRC32(CONCAT_WS('|', col1, col2, col3))) as block_checksum
FROM your_table
GROUP BY FLOOR(id / 100000);

-- 目标端执行同样逻辑,然后对比每个block的checksum

第二种是基于采样的校验。全量比对太慢,可以按主键哈希取模,比如取10%的数据做精确比对。如果采样没问题,全量大概率也没问题。但要注意采样策略,不能只采头部数据,要均匀分布。

第三种是基于binlog回放的校验。如果迁移过程中记录了binlog,可以在目标端重新回放一遍,看最终状态是否和源端一致。这种方法适合增量迁移场景。

第三层:业务逻辑校验。这是最高层也是最容易被忽略的。数据字段值都对了,但业务规则可能被破坏。比如订单表和订单明细表的金额汇总对不上,用户余额表和交易流水表的轧差不平衡。这一层需要结合具体业务写校验SQL,本质上是在做数据质量的业务规则验证。

三、技术实现方案选型

市面上做跨集群校验的工具和方案不少,大致分三类:自研脚本、开源工具、商业平台。

自研脚本的优势是灵活,可以完全适配自己的表结构和业务逻辑。缺点是维护成本高,而且容易遗漏边界情况。如果团队有开发能力,我建议自研一个校验框架,核心模块包括:任务调度、分片策略、checksum计算、差异报告、告警通知。

开源工具方面,比较成熟的有:pt-table-checksum(Percona Toolkit的组件),它是基于checksum的在线校验工具,支持MySQL主从和跨实例校验;还有DataCompare、Apache Griffin等,适合更复杂的场景。pt-table-checksum的使用方式很简单:

pt-table-checksum --host=source_host --user=root --password=xxx \
  --databases=your_db --replicate=checksum_table \
  --create-replicate-table --no-check-binlog-format

它会在源和目标各建一张checksum表,自动分批计算并对比。但要注意,它对大事务、大表的性能影响需要评估,建议在低峰期跑。

商业平台方面,各大云厂商的数据迁移服务(比如阿里云DTS、腾讯云DTS、华为云DRS)基本都自带一致性校验功能,开箱即用。如果你用的是云服务迁移,优先用平台自带的校验能力,省去自己造轮子的麻烦。

四、跨集群校验的核心难点和避坑指南

做了这么多项目,我总结几个最容易踩的坑:

坑一:时间窗口选择不对。校验必须在源端停止写入或者在一个确定的一致性快照点进行。如果源端还在持续写入,你校验的那一刻数据是对的,下一秒就不对了。正确做法是先把源端切到只读或者打一个一致性快照(比如用FLUSH TABLES WITH READ LOCK配合mysqldump的--single-transaction),然后再开始校验。

坑二:忽略了字符集和排序规则差异。源集群是utf8mb4,目标集群是utf8,或者collation不一样,看起来数据一样,但比对时会报不一致。迁移前一定要确认两端字符集完全一致。

坑三:大表校验导致性能雪崩。对几亿行的表做全量checksum计算,会把源库打满。解决方案是控制并发度、限制扫描速度、在从库上跑校验、或者用分片并行但限速的方式。我的经验是单表校验速度控制在每秒不超过1万行,对业务影响可控。

坑四:只校验了结构化数据,忽略了非结构化关联。比如图片存储在对象存储里,数据库里只存了URL,迁移时数据库数据对了,但对象存储没同步过来,业务一样报错。跨集群迁移要把所有关联存储都纳入校验范围。

坑五:差异修复没有闭环。校验出不一致了,怎么修?是从源重新同步差异行,还是手动补数据?一定要有一套自动修复或者半自动修复的流程,而且修复后要二次校验。很多团队校验做了,发现问题就搁置了,这等于没做。

五、一致性校验的自动化和持续化

一次性校验只能保证迁移那一刻的数据正确。如果后续还有增量同步在跑,数据一致性是动态变化的。所以我建议把校验做成常态化机制:

第一,迁移完成后立刻跑全量校验,出报告,有问题当天修复。第二,增量同步期间,每天定时跑抽样校验,监控同步延迟和数据漂移。第三,建立数据质量看板,把校验结果可视化,出了问题第一时间告警。

从工程化角度,可以用定时任务调度框架(比如XXL-JOB、Airflow)来编排校验任务,校验结果写入专门的质量表,配合监控系统做告警。这样整个迁移过程的数据质量就是可追踪、可回溯的。

六、总结

分布式数据库跨集群数据迁移的一致性校验,不是一个简单的"跑个脚本对比一下"的事情。它需要分层设计、工具选型、性能控制、差异修复、持续监控一整套体系。数量级校验保底、内容级校验兜底、业务级校验把关,三层缺一不可。工具能买就买、能用开源就用开源,但核心的校验逻辑和修复流程一定要自己掌握。数据迁移无小事,校验做扎实了,上线才有底气。