每个数据平台最终都会长成一片沼泽:五张都叫 orders 的表,没人确定财务用的是哪一张,还有一个仪表盘因为有人修复了上游的一个缺陷而坏掉。奖章架构(medallion architecture)是应对这种混乱的简单办法。它把湖仓组织成三层:青铜层(bronze)、白银层(silver)和黄金层(gold),每一层都有一份清晰的契约,说明其数据有多可信、谁可以使用。
这个思路之所以流行,是因为它容易解释;它之所以经常被用错,也是因为它容易解释。本文结合一张可以直接改用的架构图,讲解每一层应该放什么、不该放什么,数据如何在层间流转,数据质量检查、重新处理、治理、常见陷阱,以及什么时候你根本不需要这种模式。
三层一览
这个名称来自 Databricks,其文档把这三层描述为原始层、已验证层和已丰富层。在实践中:
| 层 | 内容 | 形态 | 谁来读取 |
|---|---|---|---|
| 青铜层 | 与接收时完全一致的数据,外加摄取元数据 | 只追加,保持源格式 | 只有数据管道 |
| 白银层 | 经过清洗、类型化、去重和统一的数据 | 每个业务实体或事件类型一张表 | 数据工程师、分析师、数据科学家 |
| 黄金层 | 为特定目的构建的业务级表 | 维度模型、聚合表、特征表 | 仪表盘、管理层、机器学习、应用 |
把这些层理解为一份质量契约,而不是处理步骤的数量。青铜层承诺完整,白银层承诺正确,黄金层承诺对特定受众有用。
青铜层:全部保留,什么都不改
青铜层是原始数据落地的地方:来自对象存储的文件、Kafka 主题、来自业务数据库的变更数据捕获流,以及 SaaS 工具的导出。规则如下:
- 只追加。 在正常处理中,永远不要更新或删除青铜层的记录。
- 最少解析。 Databricks 建议在青铜层把大多数字段存为字符串、variant 或二进制值,这样上游出现意外的模式变更时也不会丢数据。
- 添加元数据:摄取时间、源系统、文件名或主题偏移量。调试和重放时都会用到。
- 保留足够长的时间以便重建。 青铜层的保留期决定了修复缺陷后,你能把白银层和黄金层回溯重算到多久以前。
青铜层包含一切,包括你事后可能后悔复制过来的个人数据。把访问权限限制在数据管道上,并考虑在摄取时对敏感字段做令牌化或加密。GDPR 数据映射图可以帮助你追踪个人数据流向何处。
白银层:让数据正确
大部分工程投入都花在白银层:
- 解析字段并赋予类型,把时间戳统一为 UTC,并标准化单位和编码。
- 对重复到达的记录去重,任何至少一次投递的数据源都会出现这种情况。
- 应用变更。 对于变更数据捕获数据源,把插入、更新和删除合并进一张反映当前状态的表。
- 统一键,让同一个客户无论来自 CRM 还是计费系统,都拥有相同的标识符。
- 隔离而不是丢弃。 未通过校验的行连同原因一起进入隔离表,让人能够看到它们。
在 Spark SQL 中使用 Delta Lake 或 Apache Iceberg 的典型白银层合并,只保留每个订单的最新版本:
MERGE INTO silver.orders AS t
USING (
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY updated_at DESC) AS rn
FROM bronze.orders_raw
WHERE _ingested_at > '2026-11-01T00:00:00Z'
) WHERE rn = 1
) AS s
ON t.order_id = s.order_id
WHEN MATCHED AND s.updated_at > t.updated_at THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
数据质量规则应该放在这道边界上。例如,Databricks 的数据管道把它们声明为 expectations,可以发出警告、丢弃违规的行或让更新失败:
CREATE OR REFRESH STREAMING TABLE silver_payments (
CONSTRAINT positive_amount EXPECT (amount > 0) ON VIOLATION DROP ROW,
CONSTRAINT known_currency EXPECT (currency IN ('USD', 'EUR', 'GBP')) ON VIOLATION DROP ROW
)
AS SELECT * FROM STREAM(bronze_payments);
无论使用什么工具,都要让规则可见,并统计被它们拒绝的行数。
黄金层:让数据有用
黄金层的表是为消费者构建的:用于财务报表的星型模型,用于管理层仪表盘的按区域每日收入,用于流失预测模型的客户特征。每张黄金层表都应该有负责人、成文的定义和新鲜度目标。“活跃客户”“净收入”这类指标定义属于这里,只写一次,而不是在每个仪表盘里重新实现。
黄金层也是为了速度而做反范式化和聚合的地方。白银层保留细节,黄金层回答问题。
批处理、流处理,或两者兼用
分层并不决定延迟。每一跳都可以是每晚一次的批处理、每小时一次的增量作业,或带检查点的持续流。许多团队从数据源到青铜层和白银层采用流式处理,让数据在几分钟内保持最新,而黄金层的聚合则按照有人查看的频率定时刷新。尽可能做增量处理:只读取上次运行以来新增的青铜层数据,正是数据增长时成本保持平稳的关键。
重新处理与历史
因为青铜层不可变,白银层逻辑中的缺陷是可以挽回的:修复代码,从青铜层重建受影响的白银层分区,再重建黄金层。Delta Lake 和 Iceberg 这样的表格式提供快照,你可以查询某张表昨天的状态、审计某次变更或回滚一次错误的加载。从一开始就要为此做好规划:保持转换是确定性的,并对表进行分区,让重建一个月的数据不必重建全部。
按层治理
在数据目录中把每一层放进各自的模式,例如 ops.bronze、ops.silver 和 ops.gold,这正是 Databricks 在自己的示例中使用的布局。然后按层授予访问权限:数据管道写入青铜层,工程师和分析师读取白银层,公司里的大多数人只读取黄金层。跨层的数据血缘能回答事故期间每个人都会问的问题:哪些仪表盘依赖这个出了问题的数据源?
陷阱
- 把“三层”当成铁律。 有些数据源需要更多步骤,有些则更少。重要的是契约,而不是跳数。
- 在白银层写业务逻辑。 白银层应该能被许多消费者复用。只服务于某一份报表的逻辑属于黄金层。
- 把黄金层当成垃圾场。 没有负责人,黄金层就会塞满没人维护的一次性表。定期审查并下线它们。
- 所有数据复制三份。 大型原始数据集以三种形式存储,会带来实实在在的开销。白银层只保留人们真正需要的列和历史。
- 跳过隔离。 悄无声息地丢弃数据行,正是数字在没人察觉的情况下逐渐偏差的原因。
什么时候奖章架构是多余的
如果你的数据能轻松放进一个云数据仓库,而且只来自少数几个数据源,你可能根本不需要湖仓。dbt 常用的 staging、intermediate 和 marts 约定,在单个数据仓库内表达的是同一种逐步精炼的思路:
| 奖章层 | 大致对应的 dbt 层 |
|---|---|
| 青铜层 | 由摄取工具加载的原始源表 |
| 白银层 | staging 和 intermediate 模型 |
| 黄金层 | marts |
名称不如纪律重要:原始数据完整保留,每个实体只有一个干净的版本,以及有负责人的专用表。
奖章架构图
图表内容
- Orders DB (CDC)
- clickstream events
- CRM export
- BRONZE · raw, append-only
- raw/ as received
- SILVER · clean, conformed
- silver.orders, silver.customers
- quarantine: failed checks
- GOLD · business-ready
- gold.daily_revenue, dim_customer
- BI dashboards
- Churn features
- change events
- events
- daily file
- parse, dedupe, merge
- failed checks
- aggregate, model
- metrics
- features
这张图的读法如下:
- 左侧是数据源:来自 Postgres 的变更数据、来自 Kafka 的事件和一份 CRM 导出。
- 三个彩色框架代表各层。青铜层存放原始文件,白银层存放清洗后的表和一个隔离存储,黄金层存放业务表。
- 框架之间的连线是数据管道的步骤,并标注了各自的操作:解析、去重、合并、聚合。
- 右侧是消费者:BI 仪表盘和用于机器学习的特征存储只从黄金层读取。
- Markdown 块列出了每一层的契约。
画出让人一看就懂的数据平台图
- 给各层上色。 青铜、白银和黄金之所以好记,正是因为它们很直观;把颜色用起来。
- 为每一跳标注操作,而不只是画一个箭头。“去重并合并”能告诉评审者该去哪里找缺陷。
- 标明谁读取什么。 按层授权是一项设计决策,图上应该清楚表明仪表盘从不读取青铜层。
- 画出隔离路径。 它向评审者展示了被拒绝的数据去了哪里。
湖仓周边更完整的数据管道见数据管道架构图,流式数据源见 Kafka 架构图,机器学习消费者见 MLOps 架构图。
在 Archboard 中构建
- 使用 Google 或 GitHub 登录,并新建一张图。
- 作为数据源,添加数据节点包中的 Postgres 节点和 Kafka 节点,再添加一个 C4 模型节点包中的 外部系统 表示 CRM。
- 添加三个基础 框架 节点,分别命名为 Bronze、Silver 和 Gold,并配上相应的颜色。
- 在青铜层中添加一个数据节点包中的 对象存储库 存放原始文件。在白银层中添加一个 数据仓库 节点存放清洗后的表,再添加一个 对象存储库 作为隔离区。在黄金层中再添加一个 数据仓库 节点存放业务表。
- 作为消费者,添加一个基础节点包中的 方框 表示 BI 仪表盘,以及一个 ML 节点包中的 特征存储。
- 为每条连线标注对应的步骤,再添加一个基础节点包中的 Markdown 块,写上各层规则。
这个示例共用 13 个图表节点,在 Free 套餐的限制之内。
常见问题
什么是奖章架构? 一种把湖仓组织成三个质量递增层次的方法:青铜层存放接收时的原始数据,白银层存放清洗和统一后的数据,黄金层存放为特定用途构建、可直接用于业务的表。
白银层和黄金层有什么区别? 白银层以明细粒度保存正确且可复用的数据,每个实体或事件类型一张表。黄金层保存为特定目的而整理的表,例如聚合表、星型模型或机器学习特征,并配有负责人和定义。
青铜层的数据需要修改吗? 在正常处理中不需要。青铜层只追加,这样你才能重建下游的一切。例外情况是法律要求的删除请求和保留期限制,它们需要单独的流程。
奖章架构只适用于 Databricks 吗? 不是。这个名称来自 Databricks,但这种模式适用于任何湖仓或数据仓库:Delta Lake、Apache Iceberg、Snowflake 或 BigQuery,搭配 Spark、dbt 或其他工具。
我总是需要三层吗? 不是。数据源需要多少步骤就用多少步骤。关键在于保留一份未经改动的原始副本、每个实体只有一个干净的版本,以及有负责人的专用表。