异构数据同步最怕什么?不是同步慢,而是数据对不上
做数据库迁移的时候,有一个问题我觉得比性能更让人头疼:
数据到底有没有真的迁对?
这个问题在项目没上线之前,很多人其实不会特别在意。
因为迁移阶段大家关注的通常都是进度:今天迁了多少张表,还有多少存储过程没改,增量同步延迟多少,什么时候能割接。
但真正到了切库那天,关注点一下就变了。
源库 1000 万条,目标库也是 1000 万条,然后呢?
能证明两边完全一样吗?
不能。
这也是我后来研究 KFS 时比较关注的一块:数据同步完成以后,它到底怎么证明数据是对的?
COUNT(*) 对得上,远远不够
以前做数据库迁移,最简单粗暴的办法就是查数量。
sql
SELECT COUNT(*) FROM t_order;
Oracle 查一次,目标数据库再查一次。
两个结果都是:
text
12586231
看起来没问题。
但这个结果最多只能说明:
两张表的记录数量一样。
至于是不是同样的 12586231 条数据,它证明不了。
比如源库:
text
id=1001 amount=100
id=1002 amount=200
目标库:
text
id=1001 amount=200
id=1002 amount=100
COUNT 一模一样,但数据已经错了。
更麻烦的是,生产数据库通常还在持续写入。
你刚查完源库的 COUNT,业务又进来 500 条数据;等你查目标库的时候,KFS 可能已经同步过去 300 条。
于是:
text
源库:10000500
目标库:10000300
差 200 条。
这时候到底是同步异常,还是正常的同步延迟?
光看数量其实判断不了。
所以真正的数据校验,不能只解决"怎么比",还得先解决另外一个问题:
比较的到底是不是同一个时间点的数据。
这才是在线数据校验比较麻烦的地方。
为什么异构数据库的数据校验更难
如果两边都是同一种数据库,事情相对简单一些。
但实际国产化迁移经常是:
text
Oracle → KingbaseES
MySQL → KingbaseES
SQL Server → KingbaseES
PostgreSQL → KingbaseES
这时候很多东西都可能发生变化。
数据类型映射是一个。
字符编码是一个。
NULL、空字符串、时间精度、数字精度又是一个。
再加上同步过程中还有 INSERT、UPDATE、DELETE,以及事务提交顺序的问题。
所以数据迁移并不是简单的:
text
源端数据 → 复制 → 目标端
实际更接近:
text
源数据库
↓
日志解析
↓
数据转换
↓
网络传输
↓
SQL转换
↓
目标端批量写入
↓
事务提交
其中任何一步出问题,都可能留下数据差异。
KFS 本身也是基于数据库增量日志进行数据捕获和实时同步的,官方资料里提到支持 DML/DDL、过滤转换、断点续传、重连重试以及在线数据比对修复。
这几个能力其实是连在一起的。
同步负责把数据送过去,断点机制负责故障之后知道"从哪里继续",校验负责回答"送过去的数据到底对不对"。
少一个都不太踏实。
KFS 的思路:同步和校验不要拆成两套系统
这点我觉得比单纯讲某个算法更有意思。
很多项目里的数据校验其实是后补的。
迁移工具负责迁移,迁完以后 DBA 再写 SQL 校验。
最后现场经常会变成这样:
text
迁移:一套工具
同步:一套工具
COUNT:人工 SQL
抽样:人工 SQL
差异数据:Excel
修复:人工 UPDATE
数据量小时还能这么干。
几十 TB、几百张甚至几千张表以后,这种方式基本就开始失控了。
KFS 的处理方式是把同步、校验和修复放到一条链路里。
官方产品资料中明确提到:
支持全自动在线数据一致性校验与修复。
而且不只是简单比数量,还支持全量详细比对、筛选过滤比对、抽样比对和摘要比对。
这样就有点不一样了。
不是迁完以后再问:
"我们是不是还得找个工具校验一下?"
而是在迁移方案设计的时候,就把校验作为整个链路的一部分。
在线校验最关键的,其实是找到一个共同基准
这里可以结合 KFS 的断点机制来理解。
CDC 同步一直在往前跑:
text
Oracle
│
│ Redo
↓
KFS
│
│ INSERT / UPDATE / DELETE
↓
KingbaseES
假设某一时刻:
text
源端已经产生到:1005
目标端已经提交到:1000
这时候直接比较两边当前数据肯定会出现差异。
因为 1001~1005 本来就在同步路上。
因此要做可靠的数据一致性判断,首先要把比较范围确定下来。
KFS 的目标端入库设计本身就维护同步位点。
它的正常提交流程大致是:
text
事件到达
↓
逐行回放 / Batch写入
↓
事务处理完成
↓
commit
↓
写入断点
↓
位点持久化
只有事务真正提交以后,位点才跟着推进。
这个设计很重要。
因为数据库里"写过"与"已经成功提交"是两回事。
有了这个位点之后,校验至少有机会回答:
我现在比较的是哪一个同步位置的数据?
而不是拿两个不断变化的数据集硬比。
多通道同步以后,事情会更复杂
单线程同步还比较好理解。
但 KFS 为了提高目标端写入能力,可以使用多个通道并行处理。
结构大概是:
text
┌→ Channel 0 → Connection 0
事件 → Partitioner
├→ Channel 1 → Connection 1
├→ Channel 2 → Connection 2
└→ Channel N → Connection N
这样性能确实上去了。
问题也跟着来了:
每个通道处理到的位置可能不一样。
比如:
text
Channel 0 → seqno 100
Channel 1 → seqno 99
Channel 2 → seqno 97
系统突然挂了。
恢复的时候从哪里继续?
从 100 开始肯定不行,因为 Channel 2 还有数据没处理。
KFS 的方案是维护每个通道自己的处理位点,并记录待处理状态。恢复时先找到安全的重发起点,再判断哪些数据已经提交、哪些需要重新回放。
文档里给了一个很直观的例子:
text
Channel 0 = 100
Channel 1 = 99
Channel 2 = 97
重发起点 = min = 97
lastMaxPoint = 100
97~100 之间不是无脑全部重新执行。
已经提交的数据跳过,没有提交的数据重新回放,100 之后再恢复正常同步。
这其实已经不只是"断点续传"四个字了。
真正困难的是:
既要敢于重放,又不能把已经成功的数据重复写一遍。
这和数据一致性本身就是一件事。
校验发现不一致,接下来才是真正麻烦的地方
以前人工做迁移时,我觉得最痛苦的其实不是发现差异。
而是:
发现差异以后怎么办?
假设一张订单表有 3000 万条数据。
校验以后发现 37 条不一致。
你接下来至少要搞清楚:
text
哪37条?
源端是什么?
目标端是什么?
哪边才是正确数据?
INSERT少了?
UPDATE漏了?
DELETE没同步?
怎么补?
补完以后怎么证明真的好了?
如果这些全部人工处理,一两条还好。
几十张表同时出现问题,很快就会变成 Excel + SQL + 人肉对账。
所以我比较认可 KFS 的一个设计点:
校验和修复放在一起。
产品资料里明确写了:
全自动在线数据一致性校验与修复,保障数据一致性可视化,无需人为介入。
也就是说,校验的最终目的不是生成一张"有 37 条数据不一致"的报告。
而应该形成:
text
发现差异
↓
定位差异记录
↓
修复
↓
再次校验
↓
确认一致
这个闭环对于真正做迁移的人来说,比"支持 MD5 校验"几个字有价值多了。
在实际项目里,这种能力到底有什么用?
KFS 产品资料里有几个真实案例,比自己假设一个"某银行"更有说服力。
比如某直辖市交通一卡通系统。
原系统的数据规模超过 12TB ,每天新增超过 500GB,而且要求 7×24 小时业务连续运行。
最终使用 KFS 做增量数据同步以及反向同步。
官方给出的项目结果是:
text
12.3TB 存量数据迁移:< 3天
每日约 500GB 增量:秒级同步
数据一致性:不停机自动比对与修复
还有一个我觉得更能体现同步复杂度的案例:中国人民解放军总医院医疗云数据资源汇聚。
这个项目不是简单的 Oracle → KingbaseES。
源端同时存在 Oracle、SQL Server、MySQL、KingbaseES,而且操作系统还有 Windows、Linux、AIX、Solaris。
整体涉及:
text
8个院区
400+业务系统
60TB+存量数据
300GB+每日增量
项目里除了实时采集,还涉及过滤、转换、映射以及数据一致性定时校验。
这才是异构同步工具真正面对的环境。
实验室里两张表同步成功并不难。
难的是几十 TB 数据、几百套业务系统、多个数据库类型同时存在的时候,系统还能告诉你:
哪些数据同步了,处理到哪里了,两边现在是不是一致,出了问题能不能恢复。
最后聊聊我现在怎么看数据迁移
以前我做数据库迁移的时候,会把注意力更多放在"迁"。
比如:
text
迁移速度多少?
一天能跑几个TB?
同步延迟多少?
TPS多少?
这些当然重要。
但项目做多了以后,会发现真正决定你敢不敢切生产的,往往不是这些数字。
而是另外三个问题:
text
数据有没有少?
数据有没有错?
出了问题能不能回去?
尤其是 Oracle 往国产数据库迁移以后,两边不是同一种数据库,很多以前默认成立的东西都需要重新验证。
所以现在再让我设计一套迁移方案,我不会把数据校验放在最后。
而是从一开始就把:
迁移、增量同步、位点管理、数据校验、差异修复、故障恢复
当成一套完整方案。
因为迁得快,只代表项目跑得快。
数据对得上,才代表这次迁移真的完成了。