第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