3. Amazon S3数据湖基础
Amazon S3 是 AWS 上构建数据湖最常用的底座。它提供近乎无限的容量、11 个 9 的持久性和按需付费的弹性,但“把文件丢进桶里”并不等于建好了数据湖。真正决定数据湖是否好用、是否省钱、是否能被 Athena、Glue、Redshift Spectrum、EMR 等引擎高效查询的,是四件事:存储桶怎么设计、数据怎么分区、对象放在哪个存储类别、以及生命周期如何自动迁移与清理。本节围绕这四点展开,并落到一套可复用的分层目录结构上。
一、存储桶设计:命名、区域与用途隔离
S3 存储桶名全局唯一,只能包含小写字母、数字、点和连字符,长度 3~63 字符。命名建议采用“组织-用途-环境-区域”的可读模式,例如 acme-datalake-prod-cn-north-1。桶一旦创建,名称和所在区域不可更改,因此命名要在建桶前想清楚。
数据湖通常不建议只用一个桶装所有东西,而是按用途与访问模式做隔离:
- 原始区桶:接收来自业务库 CDC、日志、埋点、第三方文件的原始数据,写入频繁、几乎只追加。
- 加工区桶:存放清洗、聚合后的 Parquet/ORC 数据,供分析引擎高频读取。
- 结果区桶:存放 Athena 查询结果、报表导出、临时中间结果,可设置较短的生命周期。
- 日志与审计桶:存放 S3 访问日志、CloudTrail 日志,通常需要长期保留且访问极少。
区域选择上,应让桶与主要计算资源(Glue、EMR、Athena 所在区域)同区,避免跨区传输费用与延迟。若数据有合规要求,还需启用 SSE-KMS 加密、版本控制与阻止公共访问。版本控制对原始区尤其重要,它能防止误删或覆盖,但也会让存储量随修改次数增长,需要配合生命周期管理非当前版本。
二、分区策略:让查询只扫描必要数据
分区是数据湖性能与成本的第一杠杆。S3 本身没有索引,Athena、Spectrum 等引擎靠分区裁剪(partition pruning)减少扫描量。分区键应选择查询中最常出现在 WHERE 条件里的维度,典型是日期与业务维度。
推荐的分区路径形如:
s3://acme-datalake-prod-cn-north-1/curated/orders/
dt=2024-06-01/region=cn-north-1/orders-0001.parquet
dt=2024-06-01/region=cn-north-1/orders-0002.parquet
dt=2024-06-02/region=cn-north-1/orders-0001.parquet
这里使用 Hive 风格的 key=value 目录,Glue 爬虫和 Athena 能自动识别为分区列。分区粒度要权衡:按天分区通常合适;若单日数据量很小(例如几 MB),按天会产生大量小文件,反而拖慢查询,此时可按月分区。反之,若单日数据达数百 GB,可再按小时分区。
分区设计的三条经验规则:
- 基数适中:分区键的取值数量不宜过大,避免出现几十万个分区导致元数据膨胀。
- 避免热点:不要用高基数的用户 ID 直接做分区键,可考虑分桶或改用排序。
- 文件大小合理:单个 Parquet 文件建议 128 MB~1 GB,写入时通过 Glue 的
groupFiles或 EMR 的合并作业控制小文件。
三、存储类别:按访问频率选型
S3 提供多种存储类别,核心区别在于访问延迟、可用性、持久性、检索费用与存储单价的权衡。数据湖中常见的选型如下:
| 存储类别 | 典型场景 | 取回特性 |
|---|---|---|
| S3 Standard | 热数据、频繁查询的加工区 | 毫秒级,无取回费 |
| S3 Intelligent-Tiering | 访问模式不确定的数据 | 毫秒级,自动分层,有监控费 |
| S3 Standard-IA | 低频访问、需快速取回 | 毫秒级,有取回费 |
| S3 Glacier Instant Retrieval | 季度访问、需毫秒取回 | 毫秒级,取回费较高 |
| S3 Glacier Flexible Retrieval | 归档备份 | 分钟到小时级 |
| S3 Glacier Deep Archive | 合规长期留存 | 小时级,单价最低 |
选型原则:加工区与近期原始数据放 Standard;超过 30 天未访问的原始数据可转 Standard-IA;访问模式难以预测时用 Intelligent-Tiering 省去人工判断;审计与合规数据下沉到 Glacier 系列。注意 Standard-IA 与 Glacier 都有最短存储期限(分别为 30 天和 90/180 天),提前删除仍按最短期限计费。
四、生命周期策略:自动迁移与清理
生命周期规则让存储成本随时间自动下降。一条规则由“筛选条件 + 动作 + 时间”组成。下面是一个可直接参考的配置示例(JSON 形式,用于 put-bucket-lifecycle-configuration):
{
"Rules": [
{
"ID": "raw-to-ia-then-glacier",
"Filter": { "Prefix": "raw/" },
"Status": "Enabled",
"Transitions": [
{ "Days": 30, "StorageClass": "STANDARD_IA" },
{ "Days": 90, "StorageClass": "GLACIER_IR" },
{ "Days": 365, "StorageClass": "DEEP_ARCHIVE" }
],
"NoncurrentVersionExpiration": { "NoncurrentDays": 30 },
"Expiration": { "Days": 2555 }
},
{
"ID": "athena-results-cleanup",
"Filter": { "Prefix": "athena-results/" },
"Status": "Enabled",
"Expiration": { "Days": 7 }
}
]
}
解读:原始区数据 30 天后转 Standard-IA,90 天后转 Glacier IR,365 天后转 Deep Archive,7 年后过期删除;非当前版本 30 天后清理,避免版本控制带来的隐性成本。Athena 查询结果 7 天自动删除。生命周期转换按天粒度执行,且转换本身不收费,但要注意小对象转换可能不划算——小于 128 KB 的对象转 IA 后单价优势有限。
retention=long)比前缀更灵活,适合跨目录统一管理。五、数据湖分层架构实践
把上述要素组合起来,就得到经典的三层(或四层)数据湖架构:Raw(原始层)→ Curated/Processed(加工层)→ Consumption(消费层),外加 Serving 结果层。下图展示了数据从接入到消费的流向、各层对应的存储类别与生命周期动作。
落地时,Raw 层保留原始格式以便重放与审计,Curated 层统一转成列式 Parquet 并按 dt、region 分区,Consumption 层通过 Glue Data Catalog 暴露给 Athena 与 Spectrum。生命周期规则按层设置:Raw 层走“Standard → IA → Glacier IR → Deep Archive”的长阶梯,Curated 层保持 Standard 或 Intelligent-Tiering,结果层 7 天清理。这样既保证热查询性能,又让冷数据成本随时间自然下降。
最后给出一个可执行的检查清单,用于新建数据湖桶时逐项确认:桶名与区域是否符合规范;是否启用版本控制与 SSE-KMS;是否按用途分桶;分区键是否来自高频查询条件;单文件大小是否落在 128 MB~1 GB;是否为 Raw、Curated、结果层分别配置了生命周期规则;是否设置了非当前版本清理;是否用标签而非仅前缀管理保留策略。把这几点固定下来,数据湖的可用性与成本就基本可控。