CDC 落湖仓是什么
数据湖表格式让增量落湖具备主键能力,这是 CDC 能直接进湖仓的前提:Hudi 提供 upsert(COW 与 MOR 两种表类型),Iceberg 支持行级删除与 MERGE INTO,Delta Lake 提供 MERGE。典型做法是按主键把 CDC 事件合并进湖表,删除按墓碑行或直接删除处理,乱序用事件时间排序,而不是处理时间。
基本信息
| Hudi | COW(写时复制)与 MOR(读时合并)两种表类型,支持 upsert 与增量读 |
|---|---|
| Iceberg | MERGE INTO 加行级删除(v2 规范),适合大表批量合并 |
| Delta Lake | MERGE 语句与变更数据流(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;常见湖表格式的能力对照
| 格式 | 主键合并方式 | 小文件治理 |
|---|---|---|
| Hudi | upsert,COW 写时复制 / MOR 先写日志再合并 | clustering 与 compaction |
| Iceberg | MERGE INTO 与行级删除 | 重写数据文件(rewrite) |
| Delta Lake | MERGE 与变更数据流 | OPTIMIZE 与小文件合并 |
高频 merge 会产生大量小文件,元数据与查询性能会持续恶化:把压缩与合并任务纳入例行调度,而不是等问题出现再手工整理。
用处理时间排序而不是事件时间,晚到的旧事件会把新值覆盖回去,表现为数据偶发回退;CDC 事件里通常带源端时间戳与位点,优先用它们排序。