SStorpath
原理预计 25 分钟

块、文件、对象:三种存储语义

不是三种产品,是三种访问语义。选错语义,后面怎么调优都别扭。

学完这节你能做到

  • 用一句话说清三种存储各自暴露给应用的是什么
  • 给定业务场景,判断应该用块、文件还是对象
  • 解释为什么对象存储天然易扩展而文件存储难

三种存储,其实是三种语义

刚入行时很容易把块、文件、对象理解成"三种产品",于是产生一个疑问:Ceph 为什么能同时是三种?

答案是:它们不是三种产品,而是三种暴露给应用的访问语义。底层都是"把字节存到很多块盘上",区别在于对外提供什么接口、承诺什么语义。Ceph 底层只有一个 RADOS 对象存储池,上面套三层不同的翻译器,就变出了三种存储。

块存储文件存储对象存储
应用看到的一块裸磁盘目录树一个扁平的桶
访问单位扇区 / LBA 偏移文件 + 偏移整个对象
典型操作读写某个偏移open/read/write/seek/renamePUT / GET / DELETE
能否多机同时写一般不能(除非集群文件系统)
修改一个字节可以可以通常要重写整个对象
协议iSCSI、NVMe-oF、RBDNFS、SMB、CephFS、GPFSS3、Swift
扩展性较难极好

块存储:语义最少,所以最快

块存储提供的东西极其原始:一个按扇区编址的线性地址空间。它不知道什么是文件,也不知道什么是目录——那是上层文件系统的事。

# 拿到一个 RBD 块设备,它和本地盘用起来没有区别
rbd create mypool/disk01 --size 100G
rbd map mypool/disk01              # → /dev/rbd0
mkfs.xfs /dev/rbd0                 # 需要自己建文件系统
mount /dev/rbd0 /mnt/data

正因为语义少,块存储的路径最短、延迟最低。它的典型用户是:

  • 虚拟机的系统盘和数据盘
  • 数据库(MySQL、PostgreSQL)—— 它们自己管理数据布局,不需要文件系统帮忙
  • 需要独占一块高性能空间的应用
×别把一个块设备挂到两台机器上

块存储默认是单挂载语义。两台机器同时把同一个 RBD 挂载成 XFS 并写入,会因为两边各自缓存元数据而直接把文件系统写坏,且没有任何报错提示——直到某天你发现目录结构乱了。要多机共享,必须用共享文件系统(CephFS/GPFS),或者用支持共享的集群文件系统(GFS2/OCFS2)。K8s 里对应的就是 ReadWriteOnceReadWriteMany 的区别。

文件存储:好用,但元数据是代价

文件存储提供目录树和 POSIX 语义:能 seek,能改名,能设权限,能多客户端同时读写同一个目录。开发最喜欢它,因为不用改代码。

代价在元数据。每次 ls 一个目录、每次 open 一个文件、每次 stat,都要访问元数据服务。数据量可以靠加盘线性扩展,但元数据操作的扩展要难得多:

  • CephFS 靠 MDS 承载元数据,MDS 把热元数据放在内存里,内存不够时性能会锐减
  • GPFS 把元数据分布到所有节点,扩展性更好,但换来了更复杂的运维
  • NFS 的每一次元数据操作都是一次网络往返,小文件场景下网络往返次数会成为主要开销
!小文件是共享文件系统的天敌

读 100 万个 4KB 小文件,和读 100 个 40GB 大文件,数据总量可能相近,但前者要多做 100 万次元数据操作。AI 训练场景里数据集常常是海量小图片,这就是为什么 storplan 里明确写着 CephFS 不建议用于 AI 场景——它的元数据缓存受单个 MDS 的内存限制,撑不住这种压力。

对象存储:牺牲语义,换来无限扩展

对象存储把目录树扔掉了。它只提供一个扁平的键值空间:桶(bucket)里放对象(object),键就是名字。

# S3 语义:整存整取
aws s3 cp bigfile.tar s3://mybucket/backups/2026/bigfile.tar
aws s3 ls s3://mybucket/backups/

注意 backups/2026/ 看起来像目录,其实只是键名里的斜杠——对象存储没有真正的目录,所谓的"目录"是前缀匹配模拟出来的。这个设计上的取舍带来了两个后果:

  • 好处:没有目录树就没有集中式元数据瓶颈,可以横向扩展到万亿级对象
  • 坏处:不能原地改一个字节,不能 rename(rename 等于复制加删除),也没有 POSIX 锁

对象存储的典型场景:备份归档、图片视频、日志、数据湖、容器镜像仓库的后端。

判断该用哪种:看应用怎么访问数据
  • 应用要一块独占的盘、自己管布局 →
  • 多个客户端要共享同一份数据、要目录和 POSIX 语义 → 文件
  • 一次写入多次读取、按名字整存整取、量非常大 → 对象

判断依据不是"哪个性能高",而是"应用的访问模式是什么"。用错语义,后面的调优会一直很别扭。

协议地图

同一种语义可以由不同协议承载,接入时要分清:

块语义   ──┬─ iSCSI      成熟、通用、开销偏大
           ├─ NVMe-oF    高性能,需要 RDMA 或高质量 TCP 网络
           └─ RBD        Ceph 原生,内核或 librbd 客户端

文件语义 ──┬─ NFS        跨平台通用,v3 无状态 / v4 有状态
           ├─ SMB        Windows 生态
           ├─ CephFS     Ceph 原生,内核或 FUSE 客户端
           └─ GPFS       需装客户端软件,性能最好

对象语义 ──┬─ S3         事实标准
           └─ Swift      OpenStack 生态,新项目基本不再选
检查点单选

某团队要为一套 MySQL 主从集群准备存储,单实例数据量 2TB,要求低延迟。最合适的是?

检查点多选

关于对象存储,下面哪些说法是对的?(多选)

这节课的落点

  • 块、文件、对象是三种访问语义,不是三种产品;Ceph 在一个 RADOS 上翻译出三种
  • 块最快但单挂载,文件最好用但元数据是瓶颈,对象最能扩展但语义最弱
  • 小文件场景对共享文件系统的元数据压力是主要风险点
  • 选型看应用的访问模式,而不是看哪个听起来更高级

延伸资料