一、背景
金仓KFS V2版本以前在生产系统中跑得挺稳。工作原理是源端数据库先解析增量,KFS再做二次解码。部署相对简单,常规同步也完全没有问题。
但我们这套生产环境有两个比较突出的特点:1、对实时性要求高,2、业务上存在长事务与集中式批量操作。在这种高强度、并且业务低延迟容忍度的场景下,kfs V2版本会出现一个问题,源端一旦出现长事务,解析位点就容易被占住,后面的增量只能等。在这种情况下它与我们这类业务不是那么契合。
在经过与金仓原厂工程师的多轮讨论之后,我们决定升级到KFS V3版本:它的工作原理是把WAL日志读取到本地、由KFS自主解析,对源端基本无影响,同事针对长事务做了自动检测和恢复。
在经历了将近两个月的准本,升级完成后,本以为可以省心,结果凌晨告警又发到我手机上了“KFS序列长时间不变”,心头一紧,不会升级完没用吧?
二、现象:连续两天凌晨手机短信告警"序列号长时间不变"
监控告警是我们自己写的规则,实在crontab定时查询,判断规则是KFS序列号sequence在30分钟内没有变化就告警。正常同步时,序列号会随增量数据的解析不断向前推进;一旦长时间不动,通常意味着同步链路某个环节停滞,另外为了防止没有业务的时候诬告,我们还设置了心,5分钟触发一次心跳,所以半小时sequence不变一定存在问题。
梳理下短信告警的时间分别为前一天凌晨1:50、当天凌晨1:50、3:20都收到了"kfs 序列号长时间不变"的短信告警提醒,而白天复我们去查不管是数据库还是kfs都是正常的,日志也没有在告警时间段突增!这就奇怪了。
图1 告警短信:凌晨1:50、3:20连续触发"kfs 序列号长时间不变"。
特别是连续两天同一时段凌晨1:50、连续复现,这肯定不是偶发现象。第一反应就是去排查那个时间段有没有定时运行的作业。
三、排查过程
一:确认序列号是否推进
排查的方向变为序列号到底停在哪?拉取凌晨的序列号采样,结果非常明显:从00:40到03:40的三个小时里,有两个序列号半小时都不带变化的,分别是57480303和57480565。
图2 凌晨序列号采样
这说明链路并没有真正断掉,而是解析速度被严重拖慢了。这与V2时代"彻底卡死"的表现已经不同——V3是"慢",还是能正常恢复的。
二:确认解析进程还活着
序列号还在推进,说明KFS解析进程是活的。用kufl -service kes_new list -seqno 57480699查看这个卡点对应的数据,解析到的正是心跳表的一条CHECK_CONNECTION记录,时间为2026-07-09 01:03:12。
图3 该序列号对应heartbeat表的CHECK_CONNECTION事件,心跳机制在正常工作。
这一步排除了"进程hang",那么排场方向要往为什么解析慢上面靠了。
三:观察 WAL 日志分布
进一步看源端的WAL归档情况:正常时段日志密集、间隔均匀,而凌晨02:03至04:00这一段,日志文件明显稀疏、时间间隔被拉长,这正好与告警时段吻合。说明这段时间里KFS正被某种任务占住,来不及处理正常的日志推进。
图4 WAL 归档文件列表
四:定位根因
顺着这条线索,把矛头指向了DDL。直接在数据库里统计凌晨的DDL执行次数:
selectcount(*)fromflysync_kes_new.trep_sync_ddlwhereexe_time>='2026-07-09 00:00:00'andexe_time<='2026-07-09 04:00:00';结果是 577 次。
图5 统计 trep_sync_ddl
我们再看DDL到底在做什么,日志里全是DROP TABLE IF EXISTS t_temp_...——每一次都在批量删除上百张t_temp_开头的临时表。
图6 DDL 内容
到这里,问题就明朗:一个新上线的凌晨作业,在0点到4点之间执行了577次DDL、每次删除上百张临时表,把KFS的解析线程拖住,导致序列号推进缓慢,触发了"序列号长时间不变"告警。
四、客户追问的两个问题
把结果反馈后,客户又提了两个问题。相信大家看了这两个问题的解答将会对kfs的原理了解得更加透彻。
问题一:KFS V3和V2到底有什么区别
核心区别在于"谁来解析 WAL 日志"。
V2是依赖数据库解析:增量解析由源端数据库完成,把结果传给KFS做二次解码。这种模式部署简单、在常规场景中也很稳定,但对源端有一定影响(解析负载落在生产库上),且与数据库耦合较紧——遇到长事务等场景,解析位点容易受源端状态牵制,实时性会受影响。这也是它在我们这类高实时、多长事务业务中不占优势的地方。
V3是KFS自主解析:把WAL日志直接读取到本地,由KFS自己解析。对源端基本无影响,遇到异常可自愈,并针对oldestLsn过旧等老问题增加了自动检测与恢复机制。
| 维度 | V2 | V3 |
|---|---|---|
| WAL解析主体 | 源端数据库解析,KFS二次解码 | KFS读取WAL到本地,自主解析 |
| 对源端影响 | 较高,解析负载压在数据库 | 基本无影响 |
| 异常处理 | 解析异常需回退到数据库处理 | KFS自身即可处理,含自动检测恢复 |
| 长事务场景 | 解析位点易受源端牵制,实时性受限 | 专项优化,短暂变慢而非停滞 |
| 适配场景 | 常规、对实时性要求适中的同步 | 高实时、低侵入、长事务/DDL密集 |
| 心跳机制 | 不包含 | 包含 |
总的来说,KFS V3升级后有非常大的进步,把解析的主导权从数据库收回到KFS自己手上,完成了一次架构升级。
问题二:你们之前说新版V3不是会丢弃DDL吗?为什么还被DDL拖慢
这个问题的关键在于我们往往容易把两个概念混淆"丢弃"不等于"不解析"。
我们回到WAL的本质:数据库的所有变化都记录在WAL里,DDL也不例外。KFS通过解析WAL获取增量,而WAL是一条DML、DDL混在一起的顺序流。KFS必须先把WAL完整解析一遍,才能知道哪些变更要同步、哪些不要。所以即便某条DDL最终要丢弃它的同步动作,也必须先解析出来!不解析,就无从判断该不该丢。丢弃是解析之后的决策。
进一步讲,DDL会改变表结构。表结构一变,KFS内部维护的解析元数据就必须重新刷新,否则后续该表的DML会解析错乱。所以 KFS不仅要解析DDL,还要在解析后重建变化后的表结构,这一步相当耗时。当凌晨突然冒出577次DDL、每次涉及上百张表时,KFS就要反复地解析DDL、刷新表结构、再解析、再刷新,解析进度自然被大幅拖慢。所以这个告警并没有误报,它准确地反映了这批DDL引发的解析瓶颈。
五、客观看待新版本
需要强调一点:解析DDL会耗时,这件事V2和V3在基本逻辑上是一致的——它是走日志解析这条技术路线本身就要付出的成本,不是 V3的退步。
V3真正的改变在于:它不再依赖数据库解析、自身即可完成,并做了针对性的性能优化,因此在长事务等场景下更稳、更快;但在面对DDL洪峰这类极端场景时,仍会出现短暂的性能瓶颈——表现为序列号在一段时间内推进缓慢,也就是本次这张告警的由来。
这次升级的价值,可以概括为一句话:V3把V2"可能hang"变成了"短暂变慢、随后自愈"。从V2在长事务场景下解析实时性受限,到V3在DDL洪峰下短暂变慢、随后自动追平,同步链路从"可能受阻"变成了"暂时拥堵但可控"。本次排查里,序列号始终在缓慢推进、心跳表也在正常解析,正是这一点的印证。
六、复盘与建议
告警本身没有问题,怕的是不管他。"序列号30分钟不变"反映了同步进度停滞。我们要搞清楚:序列号停在哪、走得多慢、对应哪个时点的数据。带着具体的seqno去对齐,定位效率会高很多。
凌晨准点告警,第一反应就应排查同一时段的定时批处理。本次577次DDL正是一个新上线的凌晨清理作业,顺着"最近新加了什么操作"这条线索去找,能大幅缩短定位时间。
最终客户也是去找了应用去调整业务逻辑,本次问题不再发生。所以DDL需要当成重点来规划。每条DDL都要解析并刷新表结构,大批量、集中式的DDL就是同步链路的压力来源。批量删除、重建临时表的作业尽量错峰、分批执行,避免在同一窗口集中处理上百张表。
另外监控阈值也要跟着V3的特性调整。V3不会卡死但会短暂变慢,若业务上存在可预期的DDL高峰,可以针对该时段做动态阈值或告警抑制,避免可自愈的短暂瓶颈反复触发无效告警。
结语
从刚开始的告警,排查到最后,牵扯出的是WAL的解析机制、DDL的处理成本,以及V2到V3这次把解析机制的架构升级。有的时候现象很简单,但说到底需要多方的调整配合。才能使得生产系统稳定高效的运行。比如这种明显的业务设计问题我们可以提出来让应用厂商调整,而不是专牛角尖一定要产品去解决解析速度问题!
KFS从V2到V3的这次升级,改进了非常多,解决V2版本的很多痛点。作为使用者,我们要做的就是摸清它的特性、用对方式,让这条同步链路在真正的生产高峰面前也能扛住压力。