Skip to content

存储与表格式选型 ​

这一层回答三个问题:数据放在哪(对象存储)、怎么组织成表(Iceberg)、表在哪(Catalog)。

一、为什么是对象存储 ​

三条被淘汰的路 ​

方案问题
关系型数据库直接存数据量一大就性能崩溃,且无法被 Spark/Flink 直接当数据源
HDFS存储节点与计算节点耦合,扩存储必须扩计算;深度绑定 Hadoop 生态
NAS / 本地盘 / 块存储无法被计算引擎按对象方式访问,没有 S3 语义,扩不了、共享不了

对象存储是当前湖仓的事实标准:Spark、Flink、Doris、Iceberg 都支持 S3 协议。选它不是为了"新",是因为计算与存储解耦这件事只有对象存储能干净地做到。

对 S3 语义的硬要求 ​

不是"能传能下"就叫兼容。Iceberg 的提交依赖这些语义,少一条就会丢数据或写坏表:

语义为什么需要Ceph RGWSeaweedFS
读后写强一致提交 metadata.json 后立刻能读到新版本✅✅
原子覆盖写快照提交靠元数据文件原子替换✅✅
多段上传大文件(>5GB)必须分片✅✅
版本控制误删恢复、对象锁前置条件✅⚠️ 能力有限
生命周期冷数据转储、过期清理✅✅
对象锁(WORM)合规保留,防篡改删除✅❌
预签名 URL引擎/客户端直读,不暴露密钥✅✅

结论:如果只要"能跑 Iceberg",SeaweedFS 够用;如果要合规保留 + 企业级运维,必须 Ceph RGW。

实现对比 ​

维度Rook + Ceph RGWSeaweedFSMinIO(开源版)MinIO(商业版)
许可与可持续性Apache-2.0 + LGPL-2.1,社区持续发版Apache-2.0,社区维护AGPLv3,2026-04 已归档停维护商业订阅,按容量计费
S3 语义完整度完整 S3 语义,含版本、生命周期与对象锁兼容 S3,对象锁缺失兼容 S3,免费档仅单节点视产品与授权而定
数据保护多副本 + 纠删码 + 故障域分层纠删码,无对象锁纠删码,社区版无合规能力视授权而定
扩容方式存储节点池独立扩容,不牵动计算可扩,但需自建运维体系多节点需商业授权按容量订阅
K8s 集成官方 Operator:部署、扩缩容、滚动升级、自愈需自行编排与运维官方 Operator,但已无补丁厂商方案
大规模验证全球大规模商用,PB 级案例充分企业级案例少于 Ceph曾有大量使用,现无安全补丁取决于厂商

主推 Rook + Ceph RGW,备选 SeaweedFS。 两者的替换只换存储层,不搬数据、不动上层——这是"数据资产不被锁定"的兜底。

3 节点测试集群的现实 ​

Ceph 的价值在多节点、多故障域、多副本。3 台机器已经能跑 3 OSD、3 副本,比单机有意义得多,但有两个前提:

  1. 每台有一块可裸用的数据盘(未格式化),Rook 才能建 OSD;
  2. 愿意花 1.5–2 小时调 OSD、CRUSH、RGW。

如果云厂商只给"已格式化挂载"的数据盘,Ceph 基本没戏;这时用 SeaweedFS 3 节点(master 3 + volume 3 + filer 2 + s3 2)验证 Iceberg 读写,S3 endpoint、AK/SK、bucket 命名都写成配置项,生产切 Ceph 时只改配置。

测试阶段的取舍:

选择前提时间验证
SeaweedFS 3 节点普通盘30–40 min分布式 S3、多节点读写
Rook + Ceph RGW裸盘1.5–2 hOSD、CRUSH、3 副本、RGW、对象锁

验收记录里要写清楚:哪些 Ceph 能力没有验证(WORM、真实磁盘故障、跨故障域重平衡)。

容量怎么算 ​

方式可用容量适用
3 副本裸容量 ÷ 3热数据、小集群、追求简单
纠删码 4+2裸容量 × 2/3温冷数据、大容量
纠删码 8+3裸容量 × 8/11归档

实际规划再留 20%–30% 余量给快照、小文件、 compaction 临时空间。例:要存 100 TB 原始数据,3 副本至少准备 360 TB 裸盘。

二、为什么是 Iceberg ​

表格式对比 ​

维度IcebergHudiDelta LakeHive 表
多引擎支持Spark / Flink / Doris 原生支持,本栈引擎全覆盖以 Spark 为主,流式与多引擎弱于 Iceberg多引擎依赖转换层各引擎各自适配,语义不一致
协议开放性开放规范,表 = 元数据文件 + 数据文件,实现可替换规范与实现耦合较紧规范由单一厂商主导事实标准但技术已过时
变更能力表级事务 / 快照 / 行级更新删除,历史可追溯以写时复制为主,写放大明显支持只能整分区覆写
元数据与治理快照与清单文件即结构化元数据,血缘与质量可自动采集元数据开放度一般元数据体系相对封闭元数据与表文件解耦弱
与对象存储的匹配提交依赖元数据文件原子替换,正好用上 S3 强一致写需额外时间线服务与对象存储组合需调优依赖 HDFS 语义,不宜直接放对象存储
许可Apache-2.0Apache-2.0Apache-2.0,周边能力与商业版绑定Apache-2.0

Iceberg 到底规定了什么 ​

一张 Iceberg 表不是"一个目录",而是一棵树:

warehouse/db/orders/
├── metadata/
│   ├── 00001-<uuid>.metadata.json      # 表结构、分区、快照列表
│   ├── snap-<id>-1-<uuid>.avro         # manifest list
│   └── <uuid>-m0.avro                  # manifest(记录数据文件与统计)
└── data/
    ├── 00000-...-00001.parquet
    └── ...
  • metadata.json:表的当前状态(schema、分区规格、快照)。
  • manifest list / manifest:每个快照包含哪些数据文件、文件的列统计(min/max、null 数)。
  • data files:Parquet/ORC/Avro,按隐藏分区组织。

好处:

  1. 快照隔离:读写互不阻塞,历史版本可追溯(VERSION AS OF)。
  2. 隐藏分区:分区由表定义,查询不用在 SQL 里写分区字段,也不会因为分区列选错而返工。
  3. 行级变更:MERGE INTO / DELETE 走位置删除或等值删除,CDC 入湖不需要整分区重写。
  4. 引擎中立:同一张表 Spark 写、Flink 写、Doris 读,元数据不用同步第二份。

结论 ​

Iceberg 是唯一同时满足「多引擎可读写 + 元数据开放 + 行级变更」的表格式。 组件层面没有替代;真正要选的是目录类型。

三、Catalog:表在哪、谁能用 ​

先选协议,再选实现 ​

维度REST CatalogHive Metastore引擎各自直连厂商专有目录
标准与开放开放规范,实现可替换老接口,扩展靠私有约定无统一入口私有协议
引擎接入各引擎按同一接口接入,新增引擎只改连接串老引擎兼容好,新引擎逐步弃用每引擎各配一份,互不可见需厂商单独适配
元数据归属集中在 Catalog,落关系库可整体迁移集中在关系库,但技术栈老化分散在各引擎配置里归厂商,导出受限
权限与治理表级授权与凭证发放收敛到单一入口权限模型弱,靠外部兜权限散落,审计拼不出全貌视厂商实现
替换成本换 Catalog 只改引擎连接配置迁移需重建元数据每个引擎都要改需厂商迁移服务

REST Catalog 把表入口做成开放规范:元数据与权限收敛到一处,入口实现本身仍可替换。

实现对比 ​

维度Apache PolarisNessieHive MetastoreJDBC Catalog
与规范的关系REST 规范与实现同源以 Git 式分支见长,REST 为附加能力不实现 REST 规范规范里的基础实现
多引擎支持Spark / Flink / Doris 均可直接接入引擎接入面窄于 Polaris老引擎兼容好,新引擎弃用功能最简
权限与治理内置角色授权与表级授权分支能力强,权限模型较弱权限弱,靠外部兜无权限模型
能力定位通用目录,覆盖本栈全部需求强在数据版本与分支实验存量迁移期可用轻量场景
成熟度社区活跃成熟度较高但方向偏实验事实标准但技术老化功能有限
与本栈匹配元数据落 PostgreSQL需额外存储与运维需维护独立服务最简,但能力不足

主推 Polaris,备选 Nessie。 目录实现替换只改引擎连接配置,不进表数据、不动上层建模,这一层的选择风险最低。

Polaris 的几个概念 ​

概念含义建议
Realm租户隔离单元一个环境一个 realm(dev/prod 分开)
Catalog一组表 + 存储配置按数据域分(ods/dwd/dws),别只建一个
Namespace库对应业务域
Principal / Role身份与角色引擎用 service principal,人用 SSO 映射
Credential vending向引擎下发短时 S3 凭证引擎不持有长期 AK/SK

为什么元数据落 PostgreSQL ​

Catalog 的元数据操作需要事务:创建表、提交快照、改权限,任何一步失败都不能留下半张表。关系库的 ACID 是现成的,PostgreSQL 性能足够,且 Polaris 默认就支持。

MySQL 同样可以,没有本质差异;选 PostgreSQL 主要是团队栈一致 + Polaris 默认路径。

四、落地要点 ​

  1. Warehouse 布局:s3://warehouse/<catalog>/<namespace>/<table>/,一个桶装所有表,别一表一桶(桶数量、权限、生命周期都会失控)。
  2. 路径风格:Ceph RGW 与 SeaweedFS 都支持 path-style,客户端配 s3.path-style-access=true;对外只开 TLS。
  3. 凭证最小化:每个引擎一个 service principal,只授权到 warehouse 前缀;禁止用 root AK/SK。
  4. 小文件治理:流式入湖必然产生小文件,必须配三个定期任务:
    • rewrite_data_files:合并小文件;
    • expire_snapshots:过期快照,默认保留 7 天;
    • remove_orphan_files:清理失败提交留下的孤儿文件。
  5. 元数据库备份:PostgreSQL 每天全量 + WAL 归档;恢复演练每季度一次。Catalog 挂了,表还在,但"表在哪"没了。
  6. 容量与配额:bucket 设 quota,防止一个实验把存储写满;对象存储写满比数据库写满更难救。
  7. 升级路径:Iceberg 格式版本保持 v2;升级 Polaris 前先备份 PG,并确认引擎侧 REST 客户端版本兼容。

结论 ​

决策点结论备选换的成本
存储形态对象存储(S3)—不可换,是地基
存储实现Rook + Ceph RGWSeaweedFS改 endpoint + 迁数据
表格式Iceberg—换格式 = 重写数据
目录协议REST Catalog—换协议 = 改所有引擎
目录实现PolarisNessie改连接串,不搬数据
元数据库PostgreSQLMySQL导库 + 改配置