10.1 块存储 / 文件存储 / 对象存储

一句话

三者不是 “贵贱之分”,而是三种访问语义:块是裸设备(文件系统你自己管)、文件是目录树(POSIX 语义)、对象是扁平命名空间 + HTTP API(不能原地改,只能整对象替换);选错的代价不是性能,而是 “这个用法根本不存在”。

三种语义,一张表看清

维度 块存储 文件存储 对象存储
访问单位 扇区 / 4KB 块 文件(open/read/write) 整个对象(GET/PUT)
协议 iSCSI / NVMe-oF / 云盘挂载 NFS / SMB / POSIX HTTP(S) + S3 API
能否多机共享 不能(除非集群文件系统) 能(NFS/SMB) 能(天然 HTTP)
目录语义 无(要自己格式化) 有(目录树 + 权限) 无(桶 + 扁平 key)
随机写 支持 支持(锁语义弱) 不支持(整对象替换)
扩展方式 加盘 / 加 RAID / 换更大卷 加节点(元数据是瓶颈) 近乎无限(分片 + 扁平)
典型延迟 0.1–1ms 0.5–5ms(网络) 10–100ms(首字节)

性能与成本量级

指标 块 文件 对象
IOPS 高(万级–百万级) 中(元数据受限) 低(按请求计费)
吞吐 高(顺序读) 中高 高(大对象顺序)
单位成本(元/GB/月) 高 中 最低
元数据操作 无 瓶颈所在 桶级 list 有限制

一条经验:块最贵但最快,对象最便宜但最慢,文件在中间且元数据先撑不住。

用途对照

场景 选什么 为什么
数据库数据文件、WAL 块 需要低延迟随机写与 fsync
容器节点盘、系统盘 块 独占、可格式化
多 Pod 共享配置/上传目录 文件(NFS) 需要 POSIX 与多机挂载
图片、视频、备份、日志归档 对象 海量、便宜、HTTP 直出
数据湖 / 湖仓 对象 计算存储分离、弹性

落到数字:三种存储的量级

指标 块(云盘 SSD) 文件(NFS) 对象(S3)
随机读延迟 0.1–0.3ms 0.5–2ms 20–80ms(首字节)
4K 随机 IOPS 数千–数万 数百–数千 按请求计费,通常不做随机读
顺序吞吐 100–500MB/s 100–1000MB/s 数十–数百 MB/s(单连接)
单位成本 高(约 1 元/GB/月量级) 中 低(约 0.1 元/GB/月量级)
# 块:4K 随机读的真实 IOPS(fio 未在本机跑,命令与判据如下)
fio --name=r --rw=randread --bs=4k --iodepth=32 --filename=/mnt/test --size=1G --runtime=30
# 判据:iops 这一行;与云盘规格对比,低于 50% 先查队列深度与卷类型

反模式

反模式 后果
把数据库文件放对象存储 没有随机写与 fsync,事务无法保证
用块存储做 “共享盘”(两个节点同时挂) 文件系统互相踩坏(RWO 也是单节点,见 7.7 存储卷与持久化)
用 NFS 存百万级小文件 元数据操作打满,ls 都要几十秒
用对象存储做低延迟随机读写 每改一个字节要重传整个对象
只看单价不看请求费 小文件场景下请求费远超容量费(见 5.6 云成本结构)
用“云盘”承载共享文件 多节点无法安全挂载,数据互相踩坏

三条铁律

🔑 先问 “怎么访问”,再问 “多少钱”:随机写要块,共享目录要文件,海量冷数据要对象。

🔑 对象存储没有 “改”,只有 “换”;需要原地更新的数据不该放对象。

🔑 文件存储的瓶颈永远是元数据,不是带宽。

自检

Q1 一个团队把 MySQL 的数据目录放到 NFS 上,为什么一定会出问题?

▸ 答案:因为 MySQL 依赖 fsync 与文件锁的严格 POSIX 语义,而 NFS 的锁与缓存一致性是 “弱语义”:多客户端缓存、延迟写入、锁租约都可能让 InnoDB 认为 “已落盘” 实际没有,崩溃恢复直接损坏。数据库必须用块设备(本地盘或云盘)。

Q2 对象存储为什么 “不能原地修改”?

▸ 答案:因为它的数据模型是 “不可变对象 + 元数据索引”:PUT 会写一个全新对象(新版本),元数据指向新位置,旧对象由生命周期清理。这样设计才能做多副本/纠删码、跨区复制与无限扩展。原地改一个字节意味着重写整个对象,所以适合 “一次写、多次读”。

Q3 什么时候该用文件存储而不是对象存储?

▸ 答案:需要目录语义与多机并发写时:多 Pod 共享上传目录、传统应用直接读写文件路径、需要 rename/flock 之类语义。代价是元数据瓶颈与扩展上限。如果只是 “存文件、按 URL 取”,对象存储更便宜也更容易扩展。

Q4 为什么 “都放对象存储” 会成为反模式?

▸ 答案:因为对象存储的每次访问都有 HTTP 开销(10–100ms),且按请求计费。把高频小文件(如配置、缩略图元数据)放进去,延迟与请求费双高。正确分层是:热数据用块/文件缓存,冷数据落对象,用 CDN/缓存层挡在前面。

Q5 三种存储能混用吗?给一个典型组合。

▸ 答案:能,而且常见:计算节点用块盘(系统盘 + 数据库盘),共享配置/上传用文件存储,静态资源与备份落对象存储,前面再加 CDN。分层判据是 “访问频率 × 延迟要求 × 单位成本”:热、温、冷各放一层(见 10.9 存储选型)。

Q6 为什么 “对象存储便宜” 在小文件场景下可能不成立?

▸ 答案:因为它按请求计费:小文件每次 GET/PUT 都是一次请求,加上 list 与生命周期操作,请求费常常超过容量费。判断要看 “请求数 × 单价” 与 “容量 × 单价” 谁更大,而不是只看元/GB。

关联