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,可再按小时分区。

分区设计的三条经验规则:

  1. 基数适中:分区键的取值数量不宜过大,避免出现几十万个分区导致元数据膨胀。
  2. 避免热点:不要用高基数的用户 ID 直接做分区键,可考虑分桶或改用排序。
  3. 文件大小合理:单个 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 结果层。下图展示了数据从接入到消费的流向、各层对应的存储类别与生命周期动作。

S3 数据湖分层架构与生命周期流转 数据源 业务库 CDC 日志 / 埋点 / 文件 Raw 原始层 s3://.../raw/ JSON / CSV / 原始格式 Standard → IA(30d) Curated 加工层 s3://.../curated/ Parquet,按 dt/region 分区 Standard(热查询) Consumption 消费层 Athena / Redshift Spectrum EMR / QuickSight Glue Catalog 统一元数据 接入 清洗/转换 查询 生命周期时间轴(以 Raw 层对象为例) Day 0 Standard Day 30 Standard-IA Day 90 Glacier IR Day 365 Deep Archive 结果 / 服务层 s3://.../athena-results/ 报表导出 / 中间结果 生命周期:7 天过期删除 关键控制点 • 分区键:dt / region(Hive 风格) • 文件大小:128 MB~1 GB Parquet • 版本控制 + 非当前版本 30 天清理

落地时,Raw 层保留原始格式以便重放与审计,Curated 层统一转成列式 Parquet 并按 dt、region 分区,Consumption 层通过 Glue Data Catalog 暴露给 Athena 与 Spectrum。生命周期规则按层设置:Raw 层走“Standard → IA → Glacier IR → Deep Archive”的长阶梯,Curated 层保持 Standard 或 Intelligent-Tiering,结果层 7 天清理。这样既保证热查询性能,又让冷数据成本随时间自然下降。

常见误区:把分区键设成高基数字段(如订单号),导致分区数量爆炸、Glue 爬取缓慢;或忽略小文件问题,让每个分区里堆积成千上万个几 KB 的文件,Athena 查询因元数据开销而变慢。分区与文件大小需要一起设计。

最后给出一个可执行的检查清单,用于新建数据湖桶时逐项确认:桶名与区域是否符合规范;是否启用版本控制与 SSE-KMS;是否按用途分桶;分区键是否来自高频查询条件;单文件大小是否落在 128 MB~1 GB;是否为 Raw、Curated、结果层分别配置了生命周期规则;是否设置了非当前版本清理;是否用标签而非仅前缀管理保留策略。把这几点固定下来,数据湖的可用性与成本就基本可控。