重跑一次,为什么可能多出一份数据?
想象每天把同一本通讯录完整抄进仓库。某天任务失败,你按下重试,仓库里可能出现两套一模一样的联系人。数据管线也有这个问题。所谓幂等性(Idempotency),就是同一批数据处理一次或多次,最终结果都相同。它决定了失败重跑是在修复数据,还是制造重复。
本文依据一位有约七年经验的数据工程师在 Reddit 的观察与架构设想。它不是经过验证的最佳实践,也没有性能、成本或重复率数据。
原始数据先别动
帖中描述的 Databricks 方案使用 Auto Loader、Delta Lake 和 Medallion 分层:S3 landing 到 Bronze 层严格采用 Append-only——新数据只追加,不改写旧记录;去重、Upsert 和字段结构调整留到 Silver 层完成。Bronze 保存接近原始输入的数据,方便审计和重放;Silver 再把它整理成可用数据。
对于无法可靠增量抽取的 API 或旧式 SQL 数据库,作者设想每天抓取一次完整快照,并按 data_interval_start 写入 S3 的日期分区。API 是否用 JSON、RDS 是否用 Parquet,以及能否通过 COPY INTO 导入 Snowflake 或 Redshift,原帖都带有试探语气。作者还设想用 VARIANT 或 SUPER 列保存原始内容,并记录 file_name、ingest_time 等元数据,再由 dbt incremental model 在 Silver 层解析、转换类型和去重。
整洁与可追溯不能白拿
Append-only 像保留每一版原稿:历史清楚,但重复也会原样留下。Overwrite 是用新结果覆盖旧结果;Upsert 则按键更新已有记录、插入新记录。后二者能让当前表更整洁,却依赖稳定主键、明确版本规则和可靠的重跑边界。
因此,关键并不是 Bronze 要不要只追加,而是谁负责判断“两条记录其实是同一件事”。如果 Silver 层的判断规则不稳定,延后去重并不会自动得到幂等性。
局限与未知
- 原帖没有说明幂等键、批次标识、MERGE 条件、失败重试语义或历史分区重放策略,不足以证明“重复执行不重复”已经实现。
- 重跑同一天时,是覆盖原文件、生成新文件还是再次加载,材料没有交代;结果可能分别是历史丢失、文件重复或记录重复。
- Snowflake 与 Redshift 的重载和去重语义没有得到材料印证,不能把两者视作同一种实现。