异构数据同步,凭什么敢说数据不丢?——拆解金仓KFS的全周期一致性校验

前言

把一个跑了十年的Oracle核心库换成金仓数据库,中间隔着什么?
我给你数数:十几个TB的存量,每天几百GB的增量,7×24小时不能停的业务------对了,还有审计部门那句能把人问住的灵魂拷问:"切完之后,你怎么证明两边数据一条不差?"
行吧。做过异构数据同步的都懂,链路搭起来真只是万里长征第一步。真正让人半夜睡不踏实的,从来不是延迟高了两秒,而是那种"面板上一切正常,数据其实早对不上了"的情况。等对账对出问题再去找,黄花菜都凉了。

金仓的KFS(Kingbase FlySync,金仓异构数据同步软件)在这块儿下的功夫挺对路子:低侵入高性能的同步架构、内置的全周期数据一致性校验、0停机平滑迁移,再加一堆行业核心案例。这篇文章我就顺着"数据一致性"这条线,把它扒开看看。

@TOC

一、先想清楚:数据是从哪儿开始对不上的

聊工具之前,咱先把伤口亮出来。不一致的口子,我这些年见来见去,翻来覆去就那么几个。

全量和增量的接缝。 存量搬完那一秒,业务还在往里写呢。接缝处的SCN/LSN要是没对齐,得,丢数据就从这一刻开始,而且丢得悄无声息。

故障重传。 网络闪一下、进程崩一下,太正常了。重传少了丢数据,重传多了出重复,两头堵。

大事务回放。 源端一个几十万行的大事务,目标端回放到一半挂了------这算同步成功还是失败?你说尴尬不尴尬。

类型映射。 数值精度差一位、时间戳毫秒位没保住、字符集转岔了,任何一处小偏差,都是"看起来同步了,一对账懵了"。

人。 对,就是人。有人在目标端直接改了条数据做测试,改完忘了还原。别笑,这种事故我听得耳朵起茧,比你想象的多得多。

前四条,靠同步软件自己的工程质量去堵。第五条呢?软件管不了人,只能靠校验把问题揪出来。所以我说,同步和校验压根是两码事------同步负责"尽量对",校验负责"证明对"。市面上大部分工具,光顾着前面那半句了。

选型的时候,路子无非这几条,我直接摊开说:

同步路线 怎么干的 实时性 对源端的侵入 一致性上的坑
应用双写 业务代码同时写两个库 准实时 高,得改代码 任一端写失败就分叉,跨库事务基本没辙
定时ETL批量 按时间窗口抽数 分钟到小时级 中,扫描压力大 窗口内数据还在变,天生滞后
触发器/日志表 库内埋点记变更 秒级 高,每个事务多一跳 写放大,高峰期容易把业务库拖趴下
日志解析CDC 解析数据库事务日志 秒级甚至亚秒 链路环节多,更得有校验兜底

不用绕弯子,日志解析CDC就是当下的主流,KFS走的也是这条路,对标OGG那批老牌工具。但它比别家多想了一步:把校验和修复直接塞进产品里了。这也是我今天最想展开讲的部分。

二、链路长啥样:数据是怎么搬过去的

KFS的链路就三段:采集、KUFL、加载。一段段说。

采集端不搞虚的,直接读数据库的事务日志(Oracle的Redo就是典型),把INSERT、UPDATE、DELETE的最终结果解析出来。这里有个细节我特别想提一嘴:它只解析已提交的事务,没提交的中间状态、回滚操作,统统跳过。别小看这一点------日志解析量下来了,脏数据从源头就掐没了,一举两得。

中间那层叫KUFL,全称Kingbase Unified Format Log。各家数据库的日志格式差得十万八千里,KFS采集完统一封装成加密的KUFL格式再传,事务的提交顺序、ACID属性,原样躺在文件里。这设计还有个白送的好处:源端或目标端随便哪边断了,KUFL里存着断点前的最新数据,恢复了接着传就完事,不用从头再来。断点续传的底气,就搁这儿了。

加载端从KUFL里读数据,转成目标库的原生SQL,严格按源端的提交顺序入库。目标端只要能走JDBC就能加载------这也是它能对接的目标源那么杂的原因。金仓数据库KingbaseES自然不在话下,Oracle、MySQL、SQL Server、DB2、达梦、OceanBase、Gbase、openGauss这些关系库都行,往Kafka、Greenplum、ClickHouse、Hive、华为DWS这类数仓和大数据平台落也没问题。拓扑就更随意了,一对一、一对多、多对一、级联、双向随便组,跨网段、跨隔离装置的网络照样跑。

链路跑起来之后,还有三道检查在后头盯着:事务顺序(源端什么顺序,目标端就什么顺序加载)、日志连续性(序号不能断)、持久化I/O顺序。哪道对不上,链路直接拦下来报错,绝不默默吞掉。我个人很喜欢这个设计------报错不可怕,闷声吞数据才可怕。

"低侵入"这事儿多说两句。KFS不在业务库上建触发器、不加辅助表,解析的活儿全搬到自己节点上干,对生产库的开销基本就是读归档日志那点I/O。某市中心医院的迁移项目实测过:KFS进程内存稳定在1.8~1.9GB,CPU单核占用不到70%。在生产环境上过手的都知道这意味着什么------基本可以无视。

性能甩一组官方数(X86六核16G、SSD、千兆网的环境):Oracle源端解析118MB/s,KES源端101MB/s,目标端加载240MB+/s,端到端时延40ms。局域网TPCC模型下比业界同类高30%左右;广域网有4倍压缩传输,2M带宽就能撑起实时容灾------2M啊,也就家里宽带的零头,这都能容灾。

加载端为啥快?说白了就两招:攒批,加预编译复用。核心逻辑简化掉细节,长这样:

java 复制代码
// KFS目标端回放的核心套路(简化示意):攒批 + 预编译复用
PreparedStatement ps = stmtCache.getOrPrepare(sqlTemplate); // 相同SQL模板只解析一次
for (RowChangeEvent row : events) {
    ps.setObject(1, row.col(0));
    ps.setObject(2, row.col(1));   // 只重绑参数,解析那步全省了
    ps.addBatch();                 // 先攒着,不急着发
    if (batchFull() || tableChanged()) {
        ps.executeBatch();         // 一口气刷给目标库,网络往返从N次降到1次
    }
}
conn.commit();
checkpoint.persist(seqno);         // 提交成功才落断点,崩了就从这儿续

这笔账闭着眼都能算:逐条执行,一条SQL一趟网络往返;攒批之后,一批一趟。SQL模板还只解析一次。碰上跑批那种几十万行的大事务,KFS还有大事务分片、多通道并行入库的手段------按表拆,狠起来按行哈希拆。这块展开能讲一万字,先按住不表。

三、重点来了:全周期一致性校验,不停业务的那种

先说说土办法有多难受,你们感受一下。

要校验两边一张表是否一致,最直接的就是两边各算一遍行数加聚合值,再比对。源端是Oracle的话,大概这么写:

sql 复制代码
-- 源端:把关键列拼起来算摘要,大表跑一次几十分钟起步
SELECT COUNT(*) AS row_cnt,
       SUM(ORA_HASH(id || '|' || amount || '|'
                 || TO_CHAR(upd_time, 'YYYY-MM-DD HH24:MI:SS.FF6'))) AS chk_sum
  FROM finance.settle_detail
 WHERE upd_time >= TRUNC(SYSDATE);   -- 想只比增量?时间戳自己维护去

然后目标端还得再写一份等价的。函数名不一样,时间格式不一样,时区差一毫秒,摘要立马对不上。对不上的时候你根本分不清:是数据真丢了,还是SQL写岔了?更狠的是,这种查询赶在业务高峰扫大表,源端直接被扫到报警。于是大家只好排到凌晨两三点的"业务低峰期"去跑。

听着挺合理对吧?问题是有系统压根没有低峰期。301医院(解放军总医院)的数据汇聚项目就卡在这儿------8个院区、400多个业务系统、60多TB存量、每天300GB往上的增量,医疗业务全天候转,你跟我说哪个小时是低峰?凌晨三点急诊科可不这么认为。

KFS的思路是真换了个角度:校验压根不去"查"源端业务库,而是把同步链路本来就拿到的数据复用起来。拆开就两层。

存量校验,靠快照。源端目标端各拍一份快照,俩静态视图搁那儿比,业务该写写该读读,完全不耽误。你肯定要问:快照怎么保证两边是同一个逻辑时点?问得好。源端事务解析的时候带编号,快照和编号做映射;目标端装载到对应编号的事务时,暂停装载、取快照。这么一来,两边比的就是同一瞬间的数据,没得耍赖。

增量校验,靠KUFL。同步链路本来就把增量变更存在KUFL文件里了对吧?校验模块直接从KUFL里捞指定时间段变化的数据,搁进内存哈希表,再去目标端查对应记录核对。全程不碰源端数据库,源端零压力。这是整个方案里我认为设计得最漂亮的一笔,等于把同步链路的劳动成果白嫖了个遍(褒义)。

范围和效率上,给了几种打法按需组合:

校验方式 怎么干的 适合啥场景
全量详细比对 两端快照后逐行核对 上线前的最终确认
筛选过滤比对 只比指定的模式、表、字段 核心账务表重点盯防
抽样比对 按比例抽数据行 超大表的日常巡检
MD5摘要比对 列值拼起来算摘要再比 大宽表,省传输省比对量
多线程比对 多表并发校验 压缩整体校验窗口

效果直接上数,不整虚的。100GB数据的平均校验时间,分钟级;在线校验速率100MB/s上下。侵入性有两组实测摆这儿:301医院项目,校验速率98MB/s,校验期间业务机CPU负载增加不到3%、内存加4G以内,校验准确性100%;人行征信中心那个项目,存量4TB+、日增50GB+,以前全表校验一遍6小时起步,改成基于KUFL的增量校验,10分钟内跑完,CPU负载增加照样压在3%以内。还有中汇亿达的金融项目,2TB数据1小时比完,约25万行每秒。

CPU增加不到3%是什么概念?跑校验的时候你去业务机上top一眼,基本看不出它在干活。

哦对,还有个容易漏掉的点:校验链路和同步传输链路是分开的。开校验不拖累同步,同步高峰校验也不排队。任务想立即触发就立即触发,想定时跑一遍、按周期自动跑,界面上点点就配好了。存量加增量全覆盖------这就是"全周期"仨字的实际含义,不是宣传词儿,是两种机制各管一段,实打实。

四、校出差异之后:修复才是闭环

校验发现问题,才走完一半。怎么处理,决定这套东西好不好用。

KFS发现两端对不上,第一时间邮件、短信、微信、钉钉,哪个顺手推哪个。然后你面前摆两条路。

**手动修。**可视化界面选中差异表,定位到具体记录,做记录级修正。涉及账务的数据,估计你也不放心让程序自动动它------先人眼过一遍再改,稳。

**自动修。**打开全自动数据修复,比对出的差异KFS直接修掉,全程不用人盯。链路多、表多、7×24跑的系统就吃这套------白天人看着,晚上和节假日它自己收拾自己。

手工修大概是这个感觉(从源端捞一行,补到目标端),KFS把这动作自动化了:

sql 复制代码
-- 差异报告定位到某条记录后,修复的本质就是把这一行对齐
UPDATE finance.settle_detail t
   SET (amount, upd_time) = (SELECT s.amount, s.upd_time
                               FROM src_link.finance.settle_detail s
                              WHERE s.id = t.id)
 WHERE t.id = '20260904000123';

图形界面装不了的环境(安全要求苛刻的生产网段,懂的都懂),KFS还有命令行版的校验修复工具,功能一点不打折。

修复的底气来自链路自己的容错:断点续传,故障恢复后从断点接着来,不重传;数据库、网络、同步程序出问题,实例自动重启、自动重连;再往上还有多实例热备,主同步节点挂了备节点直接接管,实测切换10秒以内,全程不用人伸手。

北京市政交通一卡通的清结算系统,算是把这整套全用上了的综合案例:1.8亿用户、12.3TB存量,Oracle集群整体搬到KES读写分离集群,存量迁移3天内搞完,之后每天500GB增量保持秒级同步,一致性就靠不停机的实时自动比对加修复。清结算这业务,一分钱都错不得,这场景都能跑住,还有什么好挑的。

五、把校验塞进迁移流程:0停机切换的正确姿势

前面这些能力攒一块儿,才是KFS的平滑迁移方案。四步:

  1. KDMS迁移评估工具做结构迁移;
  2. KDTS迁移工具基于SCN/LSN快照搬全量;
  3. 全量一启动,KFS同时开始解析全量起点之后的增量日志,缓存在本地。这步是灵魂------全量跑三天还是三礼拜都无所谓,增量一直在那儿攒着,跑不丢;
  4. 全量完事儿,KFS把攒下的增量灌进目标库,直到两端SCN/LSN完全追平。这时候停应用,连接串一改指向新库,重启,收工。

业务真正停的时间,就最后切的那一小下。TB级存量,停机从"按天算"压到小时级甚至更短。

还想再稳一点?上双轨并行。新库上线不拆旧链路,反向同步拉起来,新旧两套库实时一致地并跑。新系统真出幺蛾子,随时切回去,进可攻退可守;等行业验证充分了,旧库再光荣退休。国产化替代走这条路,晚上能睡踏实。

写在最后

选异构同步工具,大家眼睛都盯着"支持多少种数据源""延迟几毫秒"。这些当然要看,但我劝你把另一个问题排到第一位:它怎么证明数据是一致的?

四个硬标准,自己对着量:校验是不是内置的,别回头再买工具写脚本;是不是在线的,不停业务、别把源端拖垮;存量增量是不是都罩得住;出了差异能不能自动修。四条全占,"数据无忧"这四个字才不算吹。

金仓KFS交的答卷------快照比对加KUFL增量校验、校验期间源端CPU负载增加3%以内、全自动的记录级修复------说实话,同类里我把话放这儿:能做到这么全的,少见。再加上301医院、人行征信、市政一卡通这些在产环境里真跑着的案例,选型的时候值得拉进来认认真真测一轮。

毕竟嘛,同步工具随时能换。丢出去的数据,可就真追不回来了。

相关推荐
天天进步201544 分钟前
Pixelle-Video 源码解析 #17:TTS 语音生成:Edge-TTS、Index-TTS 如何接入?
前端·数据库
海浪仙人掌1 小时前
账龄分析的定义是什么?账龄分析有什么作用?
数据库
ACP广源盛139246256731 小时前
M6/M5 Pro Mac mini 端侧 AI 落地@ACP#IX6024 PCIe2.0 交换芯片在轻量化 AI 服务中的机会与应用场景
大数据·数据库·人工智能·嵌入式硬件·macos·开源
ly76891 小时前
深入解析 MySQL 间隙锁:从加锁规则到死锁案例
数据库·mysql·死锁·间隙锁·next-key lock·事务隔离
LRL_1 小时前
7x24小时不停机:基于 Apache SeaTunnel 实现 Oracle to Oracle 实时 CDC 同步全实战
数据库·oracle·apache
不剪发的Tony老师1 小时前
Navop:一款工具搞定数据库、SSH、SFTP、远程桌面、AI Agent
运维·数据库·ssh
程序员-Benothing1 小时前
MySQL 中 DELETE、DROP 和 TRUNCATE 的区别是什么?
数据库·mysql
lhldsg1 小时前
幼儿托管系统开发实战指南:从需求分析到架构设计全流程解析
数据库·数据仓库·需求分析
2601_960356381 小时前
库存分析岗位秋招准备:SQL、Excel、WMS与供应链指标
数据库·sql·excel