第3章:数据湖核心技术栈选型

数据湖的技术栈选型,说白了就是一场「搭积木」的游戏。但积木选错了,后面想改就难了。我见过太多团队,一开始随便选,半年后哭着重构。

这一章,咱们把四个核心组件掰开揉碎讲清楚:对象存储、计算引擎、表格式、元数据服务。每个我都会给出实战建议。

3.1 对象存储选型:S3 / OSS / ADLS

对象存储是数据湖的底座。数据全放这,选错了就是给自己挖坑。

三大主流选择:

特性 AWS S3 阿里云 OSS Azure ADLS Gen2
一致性模型 最终一致性(新对象读写一致) 强一致性 强一致性
分层命名空间 不支持(需模拟) 不支持(需模拟) 原生支持
ACL 权限 Bucket Policy + IAM RAM + Bucket Policy RBAC + POSIX ACL
数据湖生态 最成熟 国内生态好 与微软系深度集成
成本(冷数据) Glacier 极低 归档存储低 Cool/Archive 分层

我的选型建议:

  • 如果你用 AWS 全家桶:无脑选 S3。生态最全,Spark、Trino、Flink 都有原生支持。
  • 如果你在国内,且用阿里云:OSS 是唯一选择。注意 OSS 没有原生分层命名空间,Hive 分区多时性能会下降。
  • 如果你在 Azure 上:ADLS Gen2 是首选。它的分层命名空间对 Hive 和 Spark 特别友好。

避坑指南

我曾经在一个项目中,团队选了 S3 但没开启「对象锁定」功能。结果某次误删了生产数据,恢复花了整整两天。记住:生产环境一定要开启版本控制或对象锁定。

小技巧:S3 的 List 操作有 1000 条限制。如果你有上百万个分区文件,建议用 Hive 分区裁剪 + S3 Inventory 来优化。

3.2 计算引擎选型:Spark / Flink / Trino

计算引擎是数据湖的「发动机」。选型要看你的场景:批处理、流处理、还是交互式查询?

三者的定位:

  • Apache Spark:批处理之王,也支持微批流。适合 ETL、数据清洗、机器学习。
  • Apache Flink:真正的流处理引擎。适合实时计算、事件驱动、CDC 同步。
  • Trino(原 PrestoSQL):交互式查询引擎。适合 Ad-hoc 查询、BI 报表、跨数据源联邦查询。

我的实战经验:

我习惯把这三者组合使用。举个例子:

  • 用 Flink 做实时入湖,把 Kafka 数据写到 Iceberg 表里。
  • 用 Spark 做夜间批量 ETL,处理历史数据。
  • 用 Trino 给分析师做即席查询,直接查 Iceberg 表。

你想想看,如果只用 Spark 做流处理,延迟至少几秒;如果只用 Flink 做批处理,资源调度又不如 Spark 灵活。各司其职才是正道。

注意:Trino 不适合做大规模 ETL。它没有 Spark 那样的 Shuffle 优化,数据量大了容易 OOM。我见过有人拿 Trino 跑 10TB 的 Join,结果集群直接挂了。

3.3 表格式选型:Delta Lake / Iceberg / Hudi

表格式是数据湖的「灵魂」。没有它,你的数据湖就是个文件堆。

三大表格式对比:

特性 Delta Lake Apache Iceberg Apache Hudi
事务支持 ACID(基于事务日志) ACID(基于快照) ACID(基于时间线)
时间旅行 支持 支持 支持
Schema 演化 支持(加列/删列/重命名) 支持(加列/删列/重命名) 支持(加列/删列)
分区演化 不支持(需重建表) 支持(隐藏分区) 不支持(需重建表)
增量查询 通过 Change Data Feed 通过 Incremental Read 原生支持(增量拉取)
Spark 集成 最紧密(Databricks 亲儿子) 好(社区活跃) 好(Uber 贡献)
Flink 集成 一般(需额外配置) 好(原生支持) 好(原生支持)
Trino 集成 好(通过 Delta Connector) 好(原生支持) 一般(需 Hudi Connector)

我的选型建议:

  • 如果你用 Databricks:Delta Lake 是默认选择。它的优化性能最好,但要注意它是闭源的(虽然开源了协议)。
  • 如果你需要跨引擎:Iceberg 是最佳选择。它原生支持 Spark、Flink、Trino,而且社区最活跃。
  • 如果你做 CDC 入湖:Hudi 的增量查询能力最强。我有个项目用 Hudi 做 MySQL CDC,延迟控制在 1 分钟以内。

避坑指南

我曾经在一个项目中选了 Delta Lake,但后来发现 Flink 写入时经常报「并发冲突」。原因是 Delta Lake 的乐观锁机制在并发写入时容易失败。后来我们改成了 Iceberg,问题就解决了。

3.4 元数据服务选型:Hive Metastore / Unity Catalog

元数据服务是数据湖的「大脑」。没有它,你连表在哪都不知道。

两种主流方案:

特性 Hive Metastore Unity Catalog
架构 开源,基于 Thrift 服务 闭源,Databricks 专有
权限管理 需额外集成(Ranger/Sentry) 原生支持(RBAC + 行级权限)
数据血缘 不支持(需第三方工具) 原生支持(自动采集)
多引擎支持 好(Spark/Hive/Trino 都支持) 仅限 Databricks 生态
扩展性 需手动优化(分区数多时慢) 自动扩展

我的建议:

  • 如果你用开源生态:Hive Metastore 是标配。但要注意,当表数量超过 10 万时,HMS 的查询性能会下降。我建议用 MySQL 或 PostgreSQL 做后端,别用 Derby。
  • 如果你用 Databricks:Unity Catalog 是必选项。它的权限管理和数据血缘功能太香了。但代价是锁定在 Databricks 生态里。

小技巧:Hive Metastore 的 Thrift 服务默认是单线程的。高并发时容易超时。我习惯用 Nginx 做负载均衡,后面挂多个 HMS 实例。

注意:Unity Catalog 目前只支持 Databricks 的 Spark 和 SQL 引擎。如果你要用 Trino 或 Flink 查数据,就得走 JDBC 桥接,性能会打折扣。

3.5 选型总结:一个实战案例

最后,我分享一个我实际做过的选型方案。某互联网公司要做实时数据湖,场景是:

  • 数据源:MySQL CDC + 应用日志(Kafka)
  • 计算需求:实时入湖 + 夜间批量 ETL + 分析师即席查询
  • 云平台:AWS

最终选型:

  • 对象存储:AWS S3(版本控制开启)
  • 计算引擎:Flink(实时入湖)+ Spark(夜间 ETL)+ Trino(即席查询)
  • 表格式:Apache Iceberg(跨引擎兼容)
  • 元数据服务:Hive Metastore(MySQL 后端)

这个方案跑了两年,没出过大问题。唯一的小坑是:Iceberg 的元数据文件会随着时间增长,需要定期清理。我们写了个定时任务,每天清理 7 天前的快照。

嗯,选型没有银弹。关键是根据你的场景、团队技术栈、预算来权衡。别盲目追新,也别固步自封。


公众号:蓝海资料掘金营,微信deep3321