首页/数据/数据工程与 ETL 速查/CDC 落湖仓:主键 merge 与乱序处理
CDC 与同步53 条

CDC 落湖仓:主键 merge 与乱序处理

数据湖表格式让增量落湖具备主键能力:Hudi 提供 upsert(COW/MOR),Iceberg 支持行级删除与 MERGE INTO,Delta Lake 提供 MERGE。CDC 数据通常按主键 merge 到湖表,用事件时间排序处理乱序,删除按墓碑行或直接删除。

CDC 落湖仓是什么

数据湖表格式让增量落湖具备主键能力,这是 CDC 能直接进湖仓的前提:Hudi 提供 upsert(COW 与 MOR 两种表类型),Iceberg 支持行级删除与 MERGE INTO,Delta Lake 提供 MERGE。典型做法是按主键把 CDC 事件合并进湖表,删除按墓碑行或直接删除处理,乱序用事件时间排序,而不是处理时间。

基本信息

HudiCOW(写时复制)与 MOR(读时合并)两种表类型,支持 upsert 与增量读
IcebergMERGE INTO 加行级删除(v2 规范),适合大表批量合并
Delta LakeMERGE 语句与变更数据流(CDF)
乱序处理按事件时间取最新,避免晚到的旧事件覆盖新值
删除语义墓碑行(op=delete)或直接删除,取决于目标表格式能力
维护动作小文件治理:Hudi clustering、Iceberg 的 rewrite、Delta 的 OPTIMIZE

典型使用场景

  • CDC 直落湖表:把 Kafka 中的变更流按主键合并到湖仓明细表
  • 镜像表构建:为分析提供一份与业务库接近同步的最新状态表
  • 多源合并:同一实体来自多个源系统的变更在湖表中按主键归并
  • 历史可追溯:湖表格式的版本与快照能力支持回溯到某个时间点
  • 删除同步:业务库物理删除后在湖表中按主键删除对应行

按主键 MERGE(湖表)

按主键 MERGE(湖表)
MERGE INTO lake.orders AS t
USING cdc_stage AS s
ON t.order_id = s.order_id
WHEN MATCHED AND s.op = 'd' THEN DELETE
WHEN MATCHED THEN UPDATE SET t.amount = s.amount, t.status = s.status
WHEN NOT MATCHED AND s.op <> 'd' THEN INSERT (order_id, amount, status)
  VALUES (s.order_id, s.amount, s.status);

-- 乱序保护:同批内先按事件时间取最新,再合并
WITH latest AS (
  SELECT order_id, amount, status, op,
         ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY ts_ms DESC) AS rn
  FROM cdc_stage
)
INSERT INTO lake.orders SELECT order_id, amount, status FROM latest WHERE rn = 1;

常见湖表格式的能力对照

格式主键合并方式小文件治理
Hudiupsert,COW 写时复制 / MOR 先写日志再合并clustering 与 compaction
IcebergMERGE INTO 与行级删除重写数据文件(rewrite)
Delta LakeMERGE 与变更数据流OPTIMIZE 与小文件合并
高频 merge 会产生大量小文件,元数据与查询性能会持续恶化:把压缩与合并任务纳入例行调度,而不是等问题出现再手工整理。
用处理时间排序而不是事件时间,晚到的旧事件会把新值覆盖回去,表现为数据偶发回退;CDC 事件里通常带源端时间戳与位点,优先用它们排序。

易错点

  • 小文件长期不治理,元数据与查询性能持续恶化
  • 用处理时间而非事件时间排序,晚到的旧事件覆盖新值,数据偶发回退
  • 删除事件只当普通更新处理,业务库已删的数据在湖表里长期残留
  • MERGE 的匹配键选错(用非唯一列),一次合并把多行错误地改写
  • 不做同批内先取最新的预聚合,同一批多条变更的最终结果取决于执行顺序

数据来源与参考

  • Apache Hudi 官方文档(Upsert)
  • Apache Iceberg 官方文档(MERGE INTO)
  • Delta Lake 官方文档(MERGE)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌