异构数据同步的最后一公里:KFS全周期数据一致性校验与自动修复实战(下)
文章目录

上篇文章聊了KFS的整体架构和目标端入库的优化手段,包括批量提交、小事务合并、Statement缓存、多通道并行和断点续传这些东西。这篇文章终于可以聊到我最想聊的部分了——数据一致性校验和修复。
为什么说这个是"最后一公里"?因为你数据同步得再快、再稳,最后源端和目标端的数据对不上,那前面的一切努力就都白搭了。我见过太多项目,同步工具跑得好好的,大家信心满满准备切流了,结果一做数据比对,发现差了大几百条记录,然后就是无穷无尽的排查和修复,项目延期那是板上钉钉的。
KFS在数据一致性这块确实下了不少功夫,而且我觉得它的设计思路跟其他同步工具有本质区别——不是把校验当作一个附加功能,而是把它作为整个同步架构的核心组成部分来设计的。为什么这么说?因为它不是在同步完了之后才做校验,而是在同步的全生命周期里都贯穿着一致性保障——从初始搬迁阶段的错误处理,到增量同步阶段的实时校验,再到切换前的全面比对,每个阶段都有对应的机制。
数据一致性校验的几种模式
KFS的数据校验一共支持三种模式,从粗到细:
精简模式(Count比对):最简单,就是比对源端和目标端每张表的记录数。这个速度快,但粒度粗,只能发现"多了或少了"的情况。如果一条记录的内容被改错了但数量没变,这种模式就查不出来了。适用场景是日常快速巡检,或者初始搬迁完成后的第一轮验证。
MD5摘要比对:对表中的数据做MD5摘要,然后比对摘要值。这个比纯计数要精确得多,而且性能也还行。KFS支持多线程并行比对,大数据量的场景也能扛得住。适合对精度有一定要求但又不需要逐行查看差异的场景。
详细模式(逐行比对):最精确的方式,逐行比对每个字段的值。能精确到具体哪条记录的哪个字段不一致,连差异的值都能展示出来。但相应的,性能开销也最大。适合上线前的最终验证,或者出了数据不一致问题之后的排查定位。
# 命令行比对工具的用法示例
# 创建一个比对任务
$ cmdcompare create \
-name check_task_01 \
-source.host 192.168.1.10 \
-source.port 18900 \
-source.service oracle_source \
-target.host 192.168.1.20 \
-target.port 18900 \
-target.service kes_target \
-conf /opt/kfs/console/conf/table.properties \
-type all
# 比对类型可选:
# count - 精简模式,只比对记录数
# md5 - MD5摘要比对
# all - 详细比对(逐行)
# 也可以指定比对策略组合:
# 0: 无策略
# 1: 精简 + MD5
# 2: 精简 + 详细
# 3: 精简 + 详细 + 修复
# 4: MD5 + 详细
# 5: MD5 + 详细 + 修复
$ cmdcompare create ... -ploy 5 # MD5 + 详细 + 自动修复
实际使用中,我一般的建议是分层递进:先用精简模式快速扫一遍,发现数量不对再上详细模式定位具体差异。无缝校验通过特殊的快照机制避免了这种情况。
在线校验——不停业务也能做比对
这个是KFS一个挺重要的能力。很多同步工具做数据比对的时候,需要先把同步链路停掉,然后在一个"静态"的数据快照上做比对。但问题是,生产环境的业务是不能停的啊!你停一个小时的同步来做比对,万一这段时间源端有新数据进来怎么办?数据就更不一致了。
KFS的在线校验就解决了这个问题。它可以在同步链路正常运行的同时,对源端和目标端的数据进行比对。这背后其实有不少技术挑战的:
首先,同步链路在持续写入目标端,你在比对的同时数据还在变化,怎么保证比对结果的准确性?KFS的做法是通过数据库的快照隔离机制,在比对开始时获取一个一致性快照,然后在快照的基础上做比对。这样即使目标端还在持续写入,比对看到的也是某一个时间点的一致性状态。
其次,在线比对不能影响源端业务。KFS的校验查询走的是只读查询,而且通过fetchSize参数控制每次读取的记录数,避免一次性加载大量数据到内存里造成OOM。
# 校验配置参数(console/conf/下的配置文件)
# 任务并行数:同时能执行多少个校验任务,范围1~5
task.parallel.count=2
# 校验核心线程数:同时有多少张表在并行比对
# 建议设置为CPU核心线程数,提升并行度
task.pool.corePoolSize=8
task.pool.maxPoolSize=8
# 校验查询fetchSize:每批次读取的记录数,范围1~100000
# 太小了频繁查询网络开销大,太大了内存吃不消
compare.fetchSize=10000
# 校验同步fetchSize:获取差异数据的批次大小
compare.sync.fetchSize=5000
# 批量修复大小:修复时批量入库的大小
repair.batchSize=500
# 校验同步是否记录日志(是否会被再次作为增量解析)
compare.sync.log.enabled=true
# 校验结果自动清除天数(每日0点自动清除N天前的结果)
compare.result.autoClean.days=7
# 是否校验大对象字段(BLOB/CLOB等)
compare.lob.enabled=true
# 大对象校验阈值(字节),超过此长度用特殊字符串代替
compare.lob.threshold=5000000
# 修复时是否跳过超阈值的大对象
compare.lob.skipOnSync=true
关于校验线程数的配置,有个小技巧。你可以用这个命令看CPU核心线程数:
# 查看CPU核心线程数
$ lscpu | grep "Thread(s) per core"
Thread(s) per core: 2
$ grep 'processor' /proc/cpuinfo | sort -u | wc -l
16
# 核心线程数 = CPU数 × Thread(s) per core
# 或者直接:
$ cat /proc/cpuinfo | grep processor | wc -l
16
把校验核心线程数设到跟CPU核心线程数一样大,再配合调大比对程序的内存(默认4GB,可以改到8GB甚至更高),比对速度能提升不少。特别是表特别多的场景,多线程并行比对的效果很明显。
# 修改比对程序内存
# 编辑 compare/conf/wrapper.conf
wrapper.java.maxmemory=8192 # 默认4096,改成8GB
全周期一致性校验是怎么做到的
这里要展开说说KFS所谓的"全周期"到底是什么意思。按照我的理解,它覆盖了三个阶段:
阶段一:初始搬迁阶段的数据校验
用KFS做数据初始搬迁的时候(就是从源端把存量数据全量搬到目标端),KFS会统计和展现以下信息:搬迁模式及表信息、源表数据条目数、搬迁结果状态、异常错误信息,便于用户在搬迁结束后复盘。
而且KFS有个不错的容错设计:搬迁过程中如果遇到错误,支持忽略错误继续搬迁,同时把出错的数据单独保存起来,后续可以做二次搬迁。这个在实际项目里很有用,因为源端数据难免有些脏数据或者格式不兼容的情况,你不能因为一条数据有问题就停住整个搬迁流程。
搬迁完成之后,你可以直接发起一次精简模式的数据比对,快速确认两端的记录数是否一致。如果有差异,再用详细模式定位具体的差异记录。
阶段二:增量同步过程中的定期校验
数据进入增量同步阶段之后,KFS支持按需启动比对任务,包括三种触发方式:
- 立即比对:手动触发一次,适合临时需要验证的场景
- 定时一次性比对:在指定时间执行一次,适合在业务低峰期做验证
- 周期性比对:按照设定的时间周期反复执行,适合长期运行中的持续监控
调度管理配置示意:
┌──────────────────────────────────────┐
│ 调度任务名称:每日凌晨数据校验 │
│ 执行任务: │
│ [x] 订单表比对 │
│ [x] 用户表比对 │
│ [x] 支付流水表比对 │
│ [ ] 操作日志表比对(非核心,跳过) │
│ 调度策略:每天 │
│ 执行时间:02:00 │
│ 状态:● 生效 │
│ [立即执行] [启用/停用] [编辑] │
└──────────────────────────────────────┘
我建议是设置一个每天凌晨的定时比对任务,把核心业务表都加上。凌晨业务量最小,比对操作对系统的影响也最小。对于特别核心、数据量特别大的表,可以一天比对多次。非核心的表可以一周比对一次就够了。
阶段三:切换前的最终校验
当你要做业务切换(比如从Oracle切到KingbaseES)之前,需要做一次最终的全面数据校验。KFS的详细模式可以逐行比对每个字段的值,确保数据完全一致之后再切流。
切换的一般步骤是:
- 停用源端的业务系统
- 用KFS做最后一次数据验证(建议用详细模式)
- 确认数据一致后,启动目标端的业务系统
如果用了双轨并行方案,切换之前可以一直保持KFS的双向同步,两端数据实时一致,什么时候觉得没问题了什么时候切。而且如果切过去之后发现问题,还可以切回来——因为源端一直在跑,KFS也在持续同步,随时可以回退。
自动修复——从"被动发现"到"主动治理"
发现了数据不一致,接下来就是修复。这个环节KFS也做了不少文章。
手动修复有几种方式:
- 整表修复:把某张表的所有差异数据一次性同步过去
- 批量修复:当前页所有差异表批量处理
- 行级修复:选择特定的差异记录进行修复
- 按类型修复:按INSERT/UPDATE/DELETE分类修复
数据比对结果界面示意:
┌─────────────────────────────────────────────────────────────┐
│ 表名 │ 源端行数 │ 目标端行数 │ 差异数 │ 操作 │
├────────────────┼──────────┼───────────┼───────┼──────────┤
│ orders │ 1500000 │ 1500000 │ 0 │ 一致 ✓ │
│ order_items │ 4500000 │ 4499857 │ 143 │ ▶同步 │
│ user_info │ 800000 │ 799999 │ 1 │ ▶同步 │
│ payment_log │ 2000000 │ 1999998 │ 2 │ ▶同步 │
│ sys_config │ 200 │ 200 │ 0 │ 一致 ✓ │
└─────────────────────────────────────────────────────────────┘
点击"同步"之后,展开差异明细:
┌─────────────────────────────────────────────────────────────┐
│ 差异明细 - order_items │
├─────────────────────────────────────────────────────────────┤
│ 差异类型 │ 主键ID │ 差异字段 │ 源端值 │ 目标端值 │
│ UPDATE │ 100234 │ amount │ 150.00 │ 120.00 │
│ INSERT │ 100235 │ (整行) │ {...} │ 缺失 │
│ DELETE │ 100236 │ (整行) │ 缺失 │ {...} │
│ UPDATE │ 100237 │ status │ PAID │ PENDING │
│ │
│ [✓全选] [批量更新] [批量增加] [批量删除] [开始同步] │
└─────────────────────────────────────────────────────────────┘
这里有个细节值得说一下:修复操作本身会不会被增量同步再次捕获,导致无限循环?答案是不会的。KFS通过一个配置项compare.sync.log.enabled来控制校验同步操作是否记录事务日志。如果设为true,修复操作会被记录并同步到源端(适用于双向同步场景);设为false则不会。
自动修复是更高级的功能。你可以创建一个修复任务,绑定到某个比对任务上,设定触发条件:
自动修复任务配置:
┌──────────────────────────────────────┐
│ 修复任务名称:订单表自动修复 │
│ 匹配比对任务:订单表详细比对 │
│ 修复等待时间:60 秒 │
│ 修复启动阈值:差异条数 >= 10 条 │
│ 触发方式:比对完成后自动执行 │
│ │
│ 不同表可设不同阈值: │
│ order_items: >= 5 条 │
│ user_info: >= 1 条 │
│ payment_log: >= 3 条 │
└──────────────────────────────────────┘
当比对任务完成之后,如果发现的差异条数达到了你设定的阈值,KFS就会自动启动修复流程,把差异数据同步过去。整个过程不需要人工干预。修复完成后,管控台会展示修复结果,包括每个表的修复状态和修复详情。
当然,自动修复这个功能得谨慎使用。我的建议是,在双轨并行初期,先用手动修复,确认每次修复的结果都是符合预期的。跑了一段时间之后,如果觉得差异的类型和原因都比较稳定了,再开启自动修复。另外修复启动阈值不要设太低——因为同步过程中由于时序问题,可能会出现短暂的"假不一致",等增量追上来就自动一致了。阈值太低会导致自动修复频繁触发。
告警机制——出事了第一时间知道
KFS在校验过程中发现数据不一致的时候,不会只是默默记个日志就完了。它支持通过多种方式告警:
- 邮件通知
- 短信通知
- 微信告警
- 钉钉告警
这个在实际运维中很重要。你不可能24小时盯着管控台看,但只要配置了告警,数据出了问题就能第一时间收到通知。
管控台本身也提供了很完善的监控统计功能:按同步链路、按同步节点,实时展示同步数据量、同步延迟、同步速率等关键指标。还有表级的同步操作分析和性能耗时分析,哪张表同步慢了、卡在哪一步了,一目了然。当某条链路延迟突增,系统能迅速定位到具体瓶颈节点,将故障排查时间从小时级缩短至分钟级。
# 通过API检查同步状态(KFS支持RESTful API)
$ curl -s http://localhost:8080/api/v1/services/oracle_source/status \
| python3 -m json.tool
{
"serviceName": "oracle_source",
"state": "ONLINE",
"appliedLastSeqno": 158723,
"appliedLatency": 0.152,
"role": "master",
"extractorLag": 0.003,
"applierLag": 0.149
}
# 检查数据校验结果
$ curl -s http://localhost:8089/api/v1/compare/results/task_001 \
| python3 -m json.tool
{
"taskName": "daily_check",
"status": "COMPLETED",
"tablesChecked": 45,
"tablesMismatch": 2,
"totalDiffs": 15,
"autoRepaired": 12,
"pendingRepair": 3
}
几个真实案例中的数据一致性实战
说了这么多技术细节,来讲几个实际项目里KFS是怎么保障数据一致性的。这些案例都来自KFS的产品资料和技术文档,有些是我自己参与过的,有些是同行的经验分享。
案例一:解放军总医院——超大规模数据汇聚
这个项目是把解放军总医院下属8个医学中心(一、三、四、五、六、七、八医学中心以及京东医疗区)的医信系统数据归集到DWS数仓,用于数据分析治理。涉及的源库包括Oracle 11gR2/19c、SQL Server 08/08r2/12/16、MySQL 5.7/8.0、KingbaseES V8等,操作系统横跨Windows、Linux、AIX、Solaris,存量数据60TB+,日增数据300GB+,涉及HIS系统、LIS检验、电子病历、急诊、康复、护理、超声、心电等多个关键业务。
每个医学中心部署2节点KFS前置机,实时采集业务数据后经过清洗、转换再合并入湖。这个场景的复杂度在于:400多个业务系统、多种异构数据源、跨多个院区。
KFS在这个项目里的数据一致性保障方案是:采集转换延时控制在10秒以内,数据一致性定时校验,事务序列实时保障,以及多维容错机制——软件故障自动重试,网络中断断点续传。60TB的数据量级,还能保持这个一致性水平,确实不容易。
案例二:北京市政一卡通——12.3TB数据的平滑迁移
北京市政一卡通这个案子,承载1.8亿用户量,12.3TB的存量数据,早高峰三小时5900万笔交易,TPS峰值2000笔/秒,不允许业务停机。需要从Oracle 12C RAC(2+2同城容灾+1读节点)迁移到KES读写分离集群。
用KFS做增量数据同步。迁移过程中,每天500G的增量数据要秒级同步。数据一致性方面,KFS提供了不停机的自动比对和修复功能。
最终结果:存量12.3TB迁移耗时不到3天,每天500G增量秒级同步,早高峰3小时支撑5900万笔交易,单表超亿行数据,容灾故障秒级切换。晚间2小时批处理事务126万个。这个数据量级和性能指标,说实话还是挺 impressive 的。
案例三:中国人民银行征信中心——跨1000KM的双中心双活
这个案子更极端。原系统是IBM小机2节点+Oracle RAC,数据量300GB;容灾中心用海光芯片+3节点KES集群,两个中心之间距离超过1000公里。用KFS做双链路实时同步+高可用分离部署。
用户最担心三件事:有没有成熟的异地容灾产品、网络不稳定性能否保障、异构数据库存储精度是否一致。
KFS的方案是:断点续传+传输压缩,在低带宽高时延环境下实现跨地域准实时同步。数据一致性方面,KES在存储精度和数据类型上完全对标Oracle(这也是个关键点——目标端数据库本身的数据类型精度要跟源端一致,不然同步工具再怎么校验也没用),再加上KFS的全自动在线数据校验和修复,最终做到了延迟小于1秒的双中心双活。还支持异构双中心定期切换,一键切换应用无修改。
案例四:某直辖市法院——112个数据源的大集中
全市206个子系统的信息化改造,涵盖审判系统、执行系统、司法管理系统、诉讼服务系统、保障系统5大类。112个同步数据源、77条同步链路。原来是20多节点Oracle RAC加80节点Oracle单机,新系统换成鲲鹏920+麒麟V10+KES集群。
KFS在这个项目里替代了原有的DB-LINK方案。5个业务库加1个汇总库,共6个数据库集群支撑全市法院的所有核心业务。3000多个存储过程、500多个复杂视图、500多个复杂SQL,全量业务迁移上云。
这种规模的同步链路,数据一致性校验的压力是很大的。KFS的统一管控台在这里发挥了关键作用——在一个界面里管理77条同步链路的状态,按链路做表级同步操作分析和性能耗时分析。而且因为是全信创环境(鲲鹏+麒麟+KES),对同步工具本身的信创兼容性也有很高要求。
案例五:嘉实基金——60TB的TA系统迁移
金融行业的核心系统,60TB存量数据,每天1500万笔事务的跑批业务,不允许停机。从Oracle RAC迁移到KES集群(鲲鹏+麒麟V10)。
这个项目的数据一致性要求极高——金融数据差一分钱都不行。KFS提供了表级的不停机数据一致性实时自动比对与修复,业务切换时长控制在30分钟以内,跑批业务延时也控制在30分钟以内,日常业务延时小于1秒。60TB的存量数据无感平滑迁移,这个体量在金融行业里也算大型项目了。
一些实操建议和踩坑记录
最后分享一些我在实际使用中的经验教训,给大家避避坑。
1. 跨广域网场景下的比对优化
如果源端和目标端之间网络带宽比较低(比如只有2M),做详细比对会很慢,因为需要大量跨网络查询数据。这时候建议用精简模式或者MD5模式,减少跨网络的数据传输量。KFS的广域网传输优化技术有4倍的压缩比,2M带宽就能支撑实时容灾同步。但比对毕竟是额外的查询操作,在低带宽环境下还是要控制频率。
2. 命令行工具是无GUI环境的救星
有些生产环境(比如涉密网络或者安全管控严格的环境)不允许部署图形化工具,这时候KFS的命令行比对工具(cmdcompare)就很有用了。功能跟Web界面是一样的,只是操作方式不同。
# 创建比对任务并立即执行
$ cmdcompare create \
-name prod_check_$(date +%Y%m%d) \
-source.host 10.0.1.10 \
-source.port 18900 \
-source.service oracle_prod \
-target.host 10.0.2.10 \
-target.port 18900 \
-target.service kes_prod \
-conf /opt/kfs/console/conf/table.properties \
-type all \
-ploy 3 # 精简+详细+修复
# 仅创建任务不执行
$ cmdcompare create ... --create-only
# 运行已有的比对任务
$ cmdcompare run -name prod_check_20260831
# 查看比对结果
$ cmdcompare result -name prod_check_20260831
# 全局参数:
# -port 8089 控制台端口(默认8089)
# -username admin 控制台用户名
# -password admin 控制台密码
3. 双向同步场景下要注意防回环
如果你做了双向同步(A→B和B→A),一定要注意KFS的防回环机制。特别是数据校验修复这块,在业界同类产品中确实算做得比较深入的。
从产品演进来看,KFS从2009年的前身KingbaseSS V7.0开始,到2017年正式以KingbaseFlySync品牌发布,再到现在的V2 R6版本,经历了十几年的迭代。从最初只支持Oracle数据源,到现在支持30多种数据源;从简单的1对1同步,到支持1对多、多对1、级联、双向等复杂拓扑;从手动数据比对,到全自动在线校验和修复——这个演进过程本身也说明了这个产品在持续进化。
当然它也不是完美的。比如对某些小众数据源的支持还不够成熟,文档也有待完善(有些配置项的说明不够详细,得去翻源码或者问技术支持),管控台的UI设计也有改进空间。但总的来说,在国产异构数据同步工具里,KFS目前算是走得比较靠前的一个。特别是配合KingbaseES的深度适配(毕竟是自家产品),在信创场景下的整体体验是比较好的。
好了,就写到这里。如果对KFS还有什么想了解的,或者在数据同步方面有什么坑想讨论的,欢迎留言交流。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)