云选科普

实时数据同步怎么设计:从 CDC 到一致性校验

从实时目标、变化捕获到全量增量衔接,系统梳理数据库同步中的幂等写入、位点恢复、异常处理与数据校验,帮助开发者和小团队按业务需求选择方案。

实时数据同步的难点,不是把任务调成“每分钟执行一次”,而是让源库持续变化、网络偶发中断、目标库出现压力时,数据仍然不丢失、可恢复、可验证。

对多数业务来说,同步链路至少要回答六个问题:变化如何被发现,历史数据如何初始化,全量和增量如何衔接,目标端如何避免重复,失败后从哪里恢复,以及怎样证明结果可信。下面按这条链路梳理一套可落地的设计方法。

先定义同步目标,再决定技术方案

“实时”不是固定的时间单位。交易风控可能需要秒级响应,设备告警可能允许十秒级延迟,经营看板可能接受几分钟延迟,财务分析则可能按小时更新。没有明确目标就开始选 CDC、消息队列或同步平台,往往会用过高的复杂度换取并不需要的时效。

设计前建议先写清四类指标:

  • 延迟目标:正常情况下允许多长时间的数据延迟;
  • 积压目标:高峰期最多允许积压多久,恢复时要多久追平;
  • 一致性目标:是否允许重复投递,是否允许短暂不一致,删除是否必须实时传播;
  • 同步范围:哪些表只需新增,哪些表必须捕获更新和删除,哪些字段需要脱敏。

日志、流水、采集记录通常是追加型数据,适合简单的增量方案;订单、客户、库存和合同会被修改甚至删除,通常需要完整捕获变化。延迟越低,对源库日志、网络、目标端写入能力和运维监控的要求越高,因此应按业务价值设定目标,而不是单纯追求更快。

源端如何捕获变化

CDC:适合有更新、删除和较高时效要求的业务

基于数据库事务日志的 CDC 会读取 INSERT、UPDATE、DELETE 等变化事件。它通常比反复扫描业务表更适合大数据量和低延迟场景,也能保留变化顺序和删除信息。

但 CDC 的前提条件不能忽略:源库要开启所需日志,账号要具备读取权限,日志保留时间要覆盖最大故障恢复窗口。同步任务如果中断超过日志保留期,断点续传就可能失效,只能重新做全量初始化。大事务还会带来突发事件洪峰,目标库需要具备削峰和限流能力。

更新时间戳:实现简单,但必须处理边界和删除

updated_at 查询是很多项目的起点,但直接使用“更新时间大于上次时间”存在边界遗漏风险。更稳妥的做法是使用“更新时间 + 主键”作为复合游标,或者设置回溯窗口,每次多读一段时间,再通过业务主键和版本号去重。

这类方案通常无法发现物理删除。若业务必须同步删除,需要引入逻辑删除标记、删除日志表,或改用能够捕获 DELETE 事件的 CDC。

递增主键:只适合严格追加型数据

记录上次最大的 ID、下次只读取更大的 ID,适合日志和流水等只新增不修改的数据。它无法识别历史更新和删除,也不适合主键跳号、历史补录、分库合并或 ID 顺序与事务提交顺序不一致的场景。

全量初始化要和增量无缝衔接

第一次建设目标库时,不能简单地“先复制历史数据,完成后再启动增量”。因为全量复制期间源库仍在写入,两个阶段之间会形成数据空窗。

更可靠的流程是:

  1. 在全量开始前记录日志位点或等价的增量游标;
  2. 启动增量捕获,让全量期间的变化先进入缓冲区;
  3. 按主键范围、时间分区或分片读取历史数据;
  4. 全量数据写入目标端,并使用批次记录追踪进度;
  5. 将缓冲区中位点之后的变化按顺序回放;
  6. 确认目标端追平后,再切换到持续增量模式。

大型表最好拆分为可重试的小批次。不要把整张表绑定成一个不可恢复的长事务,否则一次网络故障就可能迫使任务从头开始,也会给源库带来持续压力。

传输与目标写入:把“至少一次”变成可接受的结果

在分布式链路中,追求绝对的“只传一次”通常代价很高。更常见的设计是允许至少一次投递,再由目标端保证幂等:同一事件重复到达时,可以重试,但不能形成重复业务结果。

目标写入可以采用以下方式:

  • 以业务唯一键作为幂等依据;
  • 使用 UPSERT 或 MERGE 合并新增和更新;
  • 保存事件 ID,识别已经处理过的批次;
  • 用版本号或源端更新时间防止旧事件覆盖新状态;
  • 对删除事件和状态流转设置明确的顺序规则。

位点推进顺序同样关键:读取变化、写入目标、确认成功之后,才能提交日志位点或消息偏移量。如果目标写入失败却提前推进位点,任务恢复时就无法重新获取这批数据,最终表现为静默丢数。

幂等也不等于业务正确。订单不能被旧事件回退,库存不能因重复消费被重复扣减,删除事件不能晚于重新创建事件并误删新记录。必要时应把业务版本、状态机和事件时间一起纳入写入条件。

校验、监控和异常恢复要形成闭环

同步平台显示“任务成功”,只说明程序没有报错,不代表源库和目标库已经一致。建议至少设置四层校验:

  1. 数量校验:比较新增、更新、删除和最终写入数量;
  2. 主键校验:检查源端存在但目标端缺失的键,以及目标端重复键;
  3. 字段校验:对金额、库存、状态分布、空值比例或关键字段摘要进行比较;
  4. 业务校验:验证金额、状态、关联关系和异常波动是否符合业务规则。

异常处理要区分类型。网络抖动、超时和短暂重启可以使用带退避的自动重试;字段长度超限、类型转换失败等数据问题应进入隔离表或异常队列,避免阻塞全部任务;表结构变化、主键变化和高风险类型修改则应暂停或升级告警。

监控面板还应展示延迟、积压量、读取位点、目标写入吞吐、失败批次、重试次数和校验差异。发生故障时,运维人员才能判断是源库变慢、网络堵塞、目标库限流,还是数据本身不符合约束。

不同场景的选型建议

  • 日志、流水、采集数据:若只新增,可优先考虑递增 ID 或时间窗口增量;
  • 订单、客户、库存等业务表:需要更新和删除,优先采用 CDC 或带完整变更记录的方案;
  • 首次建设数仓或读库:重点检查全量与增量的切换位点,不要把两个阶段割裂;
  • 跨系统、跨地域同步:重点评估消息积压、网络重试、目标幂等和数据脱敏;
  • 对一致性要求高的写入链路:除了技术字段校验,还要补充业务规则校验和人工处置流程。

结语

可靠的实时同步是一套闭环,而不是某个单独工具:源端准确捕获变化,全量与增量无缝连接,传输层承接波动,目标端幂等写入,位点支持恢复,校验机制确认结果。

如果只关注“能不能同步”,系统可能在正常状态下看起来没问题;只有把丢数、重复、乱序、结构变化和恢复路径都提前设计清楚,数据链路才适合长期支撑数仓、看板、风控和业务分析。

继续浏览

还想继续看,可以再看这些文章

适合想继续在同一主题下横向阅读、对比不同切入角度的用户。