多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

数据同步如何保证不重、不丢、不错?一文讲清全量、增量、校验和异常处理

数据同步如何保证不重、不丢、不错?一文讲清全量、增量、校验和异常处理 企业做数据同步真正危险的往往不是任务报错而是任务显示“成功”数据却已经重复、遗漏或失真。订单被重复写入销售额被放大历史订单发生修改增量任务却没有捕获金额字段进入目标库后精度被截断任务失败后从头重跑又制造出重复数据。因此可靠的数据同步不能只回答“能不能把数据搬过去”还要回答三个问题同一条数据重复执行会不会重复源端发生的变化有没有全部到达到达后的内容和业务含义是否仍然正确在正式展开前我整理了一份《数据仓库建设解决方案》涵盖数据建设、数据治理和企业数字化实践等内容需要的可以自取https://s.fanruan.com/7igmg复制到浏览器一、先理解“不重、不丢、不错”“不重”不是同步结束后再做一次去重而是同一批数据被重复读取、重复投递或任务重复启动时目标端最终仍然只有一份。“不丢”也不只是源表和目标表总行数相同。新增、修改、删除以及迟到数据、边界数据、停机期间的数据都可能被遗漏。“不错”则要求字段值、数据类型、编码格式、关联关系和业务口径保持一致。两边各有100万行不代表金额没有被截断、状态没有映射错误、时间没有因时区变化而偏移。所以一条可信的同步链路至少要保证四层一致记录完整、主键唯一、字段正确、业务可解释。二、全量同步难点不是“搬完”而是建立一致起点全量同步常用于首次上线、目标表重建、历史数据回补和故障恢复。最简单的做法是清空目标表再把源表全部写入。但只要源系统仍在产生业务全量期间就可能出现“动态快照”问题。例如全量任务10点开始、12点结束。期间新增或修改的数据可能被重复读取也可能被跳过。最后得到的既不是10点快照也不是12点状态。更可靠的方案是“一致性快照增量追平”全量开始前记录日志位点、LSN或时间水位在同一快照口径下读取历史数据全量写入结束后从已记录位点消费增量增量追平后再切换为持续同步。关键在于全量与增量必须共享一个明确的交接点。没有交接点两段任务之间会出现空档范围重叠却没有幂等机制又会产生重复。大表全量还要合理分片。按主键区间、日期分区或哈希分桶读取通常比不断增加offset更稳定也便于失败后只重跑局部区间。在FineDataLink中可以根据场景选择追加写入、清空目标表后写入或基于标识字段执行新增、修改和删除。初始化阶段先装载历史数据再以标识字段衔接后续变化更容易把“第一次搬全”和“后续持续更新”连成一条完整链路。三、增量同步关键是找到可靠的变化依据增量同步只处理上次任务之后发生变化的数据效率更高但同步边界也最容易出错。1、自增主键按照“主键大于上次最大值”读取适合只新增、不修改的流水表。它无法识别历史记录修改和删除旧数据补录、主键回填或主键不连续也可能造成误判。自增主键适合判断“新增了什么”却不适合判断“什么发生了变化”。2、更新时间戳按照update_time读取新增和修改是定时同步中最常见的方式。但只使用“update_time上次最大时间”并不安全。多条数据可能拥有相同时间戳数据库时间精度也可能不足位于边界上的记录容易被漏掉。更稳妥的方法是使用“时间戳主键”组成复合水位也可以把起点向前重叠数秒再依靠目标端幂等消除重复。例如上次同步到10:00:00本次可以从09:59:55开始重新读取。多取几秒的数据并不可怕只要目标端能够识别同一条记录真正危险的是把边界卡得过死导致数据永久遗漏。增量同步的原则不是“绝不重复读取”而是“允许少量重叠但不能留下数据空档”。3、业务时间下单时间、发货日期和开票日期描述业务何时发生却不一定反映数据何时修改。三个月前的订单今天被修正如果只按下单时间取增量这次变化不会进入目标端。因此业务时间适合划分分析范围更新时间才更接近技术增量边界。4、数据库日志或CDCCDC直接读取数据库日志中的插入、更新和删除事件不必反复扫描整张表适合高频变化和低延迟场景。但CDC也不是开箱即“绝对不丢”。日志保留时间不足、读取位点失效、表没有稳定主键、DDL变更不兼容都可能破坏同步连续性。FineDataLink可基于CDC、Binlog、LogMiner等方式进行实时增量同步。部署时仍要检查日志是否开启、保留多久、断点是否有效以及目标表用什么字段识别同一条记录。工具负责捕获变化工程规则决定链路能否长期稳定。四、如何保证“不重”核心不是去重而是幂等网络超时、消费端重启、写入确认丢失都可能让同一批数据再次到达目标端。工程上更常见的方案是允许数据至少投递一次但要求目标端重复执行后结果不变。这就是幂等。实现幂等需要四个条件。第一建立稳定的唯一键。订单ID、客户ID或者“来源系统业务单号”必须能够唯一识别业务对象。第二使用upsert或merge而不是无条件append目标端不存在则插入已经存在则更新内容没有变化则不重复处理。第三为事件建立版本。可以使用日志位点、版本号或更新时间判断新旧避免较晚到达的旧事件覆盖最新状态。第四正确安排提交顺序。应先完成目标端写入再提交同步断点。假设一批数据已经从源端读取但还没有写入目标端系统就提前更新了断点。此时一旦写入失败任务重新启动后会直接从新断点继续中间的数据将被永久跳过。反过来如果目标端已经写入成功但断点暂时没有提交任务重启后最多只是重复读取。只要目标端具备幂等能力重复数据就能被识别和覆盖。因此可靠同步宁可接受“可控重复”也不能接受“不可恢复的遗漏”。五、如何保证“不丢”覆盖数据的完整生命周期很多同步任务只处理新增和修改却没有处理删除。源系统删除一张无效订单目标表仍然保留报表就会继续统计业务结果已经失真。删除同步一般有三种方式从CDC日志中捕获物理删除使用is_deleted等字段同步逻辑删除周期性执行快照比对识别源端已不存在的记录。除此之外还要处理三类隐性丢数。1、迟到数据业务早已发生但因接口积压、人工补录或上游故障过一段时间才进入源表。可以设置回看窗口定期重刷最近若干天的数据。2、乱序数据先发生的事件后到后发生的事件先到。目标端不能只看接收顺序而应结合版本号或业务更新时间判断最新状态避免旧事件覆盖新结果。3、断点失效任务停机时间超过日志保留周期原来的位点已经无法继续读取。此时不能直接从最新位置启动而要重做受影响范围的全量或补数再建立新的增量起点。此外还要记录源端读取位点、目标端写入位点、每批读取量、成功量、失败量和最大更新时间。如果系统只显示“任务成功”却无法回答“同步到了哪一条、哪个时间点”一旦发生问题就只能依赖人工猜测和整表重跑。真正的不丢不是从未失败而是失败后知道停在哪里、缺了哪一段、怎样准确补回来。六、如何保证“不错”校验要从技术层走到业务层行数校验只能发现“大面积少了或多了”无法证明内容正确。一套可靠的校验机制至少要分五层。1、数量校验比较源端读取量、过滤量、成功写入量和失败量。原则上应满足读取量成功写入量过滤量失败量。任何一项没有明确去向都意味着链路存在黑箱。2、唯一性校验检查主键和业务单号是否重复一对一关系是否变成一对多。重复通常说明幂等规则失效或不同系统的标识发生冲突。3、汇总校验按日期、组织、地区、订单状态等维度比对记录数、金额和数量。总量一致而分组不一致通常意味着字段映射或状态转换出错。例如总销售额完全相同但华东地区金额减少、华南地区金额增加可能是地区编码映射发生了错位。4、内容校验对关键字段按固定顺序拼接并计算哈希。同一主键哈希不同就说明内容不一致大表可以先按分区校验再缩小范围。需要注意的是计算哈希前必须统一空值、日期格式、小数精度和字符编码否则同一条数据也可能计算出不同结果。5、业务规则校验例如订单金额不能为负退款金额不能高于实付金额发货时间不能早于下单时间客户编码必须存在于主数据中已关闭订单不能继续产生发货记录。技术同步成功只能说明数据被写进去了业务规则校验通过才能说明数据可以被使用。FineDataLink的任务日志能够暴露源端增量读取、目标端写入、连接状态和日志断点等问题。把这些运行信息与行数差异、金额差异、延迟时长一起纳入监控校验就能从月底人工对账转变为同步过程中的持续控制。七、异常处理不是简单重跑而是分类恢复同步失败后无限重试可能把临时问题变成系统雪崩也可能让错误数据被反复放大。第一类临时性异常例如网络超时、数据库短暂不可用、接口限流。这类问题可以采用指数退避重试并设置最大次数避免任务集中冲击上游。第二类数据异常例如字段超长、日期格式错误、必填字段为空。这类问题反复重试通常没有意义应进入脏数据表或隔离区保留原始记录、失败原因和批次号让正常数据继续执行。第三类结构与规则异常例如源字段被删除、类型变化、主键规则调整、目标表结构不兼容。这类问题应立即停止相关链路并告警避免错误继续向下游扩散。不是所有异常都适合重试。临时故障可以重试数据错误需要隔离结构变化必须人工确认。补数也必须遵循原来的唯一键、版本判断和校验规则否则可能制造重复或用旧数据覆盖新状态。例如补录三天前遗漏的订单时不能无条件覆盖目标表中的同一订单。因为这张订单可能已经在今天被修改三天前的旧版本反而会把新状态覆盖掉。因此一套可恢复机制必须同时保留原始输入、任务批次、处理断点、失败原因、目标结果和重放入口。异常处理真正要解决的不只是“怎样把任务重新跑起来”而是怎样在恢复任务的同时不制造新的重复、遗漏和错误。八、结语判断一条数据同步链路是否可靠可以检查六个问题全量开始时是否有一致快照和明确的增量交接点增量依据能否覆盖新增、修改和删除重复投递后目标结果是否仍然唯一断点是否在目标端写入成功后再推进校验是否从行数延伸到字段、汇总和业务规则失败后能否定位范围、隔离异常并安全补数“不重”依靠唯一键、版本控制和幂等写入“不丢”依靠变化捕获、断点管理和补偿机制“不错”依靠分层校验与业务规则。数据同步真正要建设的不是一条永远不会报错的链路而是一套即使发生中断、重复和异常也能够发现问题、恢复数据并证明结果可信的机制。
返回列表