LabHub
学习 学习路径 课程

对象存储与 S3

为什么没有文件夹

在 LabHub 中继续学习

一句话总结

object storage 中没有目录。img/2026/logo.png 只是一个包含 slash 的长 key,这一事实正是其可扩展性的基础。

概念图: key 只是长字符串 · 没有重命名。 · 必须从一开始就设计好 key。 · 没有空目录。

为什么需要了解这一点

filesystem 是一棵树。每个目录都有 inode,打开一个文件时,要沿路径向下逐级检查每一步的权限与存在性。这种结构在本地磁盘上非常出色。但如果要把 100 亿个文件分布在 100 个 node 上,问题就会出现。树的上层 node 会成为所有访问的竞争点;一个目录中放入 100 万个文件后,ls 会运行数分钟。

object storage 丢弃了树,只保留扁平的 key-value 空间。key 只是字符串,slash 没有特殊含义。mc ls 或 console 显示得像 folder,只是一个按 prefix 分组的画面。

这种简化带来的好处,是可以对 key 进行 hash 来决定放在哪个 node。无需中央 directory server,增加 node 后,容量与吞吐量会一同提升。

工作原理

相应放弃的能力也很明确。

第一,无法局部修改。object 只能整体写入或整体读取。修改 1GB 文件中间的 1 字节,也要重新上传 1GB。因此,它不适合日志文件等持续追加的数据。

第二,没有重命名。rename 是先复制后删除。要把 img/ prefix 改为 images/,必须复制并删除其下所有 object。这就是为什么要在一开始设计好 prefix。

第三,没有 POSIX 语义。不存在 file lock、hard link、atomic rename 等能力。因此不能把 database file 放在 object storage 中。

第四,列表查询成本高。虽然可以按 prefix 列表,但要查找“大小超过 1MB 的对象”或“昨天修改的对象”,就必须遍历全部内容。需要 metadata search 时,应另建 index。

实际工作中的表现

prefix 设计中常见的错误,是把日期放在最前面。使用 2026-08-20/user/... 时,当天全部写入都会集中到同一个 prefix 范围。在按 key 顺序进行 partitioning 的实现中,这会形成 hotspot。把容易分散的值放在开头(例如 user ID hash 的前两个字符)更安全。

最好也记住真正适合 object storage 的 workload:一次写入、多次读取的大型 immutable data。例如 image、video、backup、training dataset、build artifact。相反,经常局部修改的小型数据更适合 database。

当作 filesystem 使用会发生什么

S3 中没有目录,key 只是长字符串/ 只是让画面显示为树形的一种惯例。 这种差异在实际工作中表现为三点。

没有重命名。 mv 是复制 + 删除。重命名 100GB 目录, 会复制再删除 100GB。因此,必须从一开始就设计好 key。

没有空目录。 删除其中全部 object 后,该“folder”便会消失。 创建 s3://bucket/logs/ 只是创建一个 0 字节 object。

列表查询成本高。 LIST 每页返回 1,000 个对象。object 有 100 万个时, 就要往返 1,000 次。如果想着 filesystem 的 ls,每次请求都调用列表, 成本与延迟会同时增加。

如何设计 key

过去常说“必须随机打散开头才能获得性能”,但现在 S3 会按 prefix 自动分割,因此最好采用便于阅读的顺序

logs/2026/09/06/api/instance-42.jsonl.gz
  │    └ 시간 계층 — 수명주기 규칙과 부분 조회에 유리
  └ 종류

❌ 2026-09-06-api-instance-42.jsonl.gz    ← 접두로 못 자른다

把时间设为层级,可以轻松编写只删除 logs/2026/09/ 或只把该月数据转入廉价类别的 规则。相反,如果全部连成一行,就无法创建 prefix 条件。

什么时候应该使用 filesystem

object storage 并非永远是答案。

Object storage Filesystem(NFS、EFS)
局部修改 不可(整体重新上传) 可以
重命名 复制+删除 立即完成
lock
POSIX 语义
可扩展性 实际近乎无限 有上限
单价 便宜 贵数倍

如果现有应用会局部修改文件或使用 lock,就不能直接迁移到 object storage。 虽然可以通过 s3fs 等工具挂载,但局部修改会变成整体重新上传,lock 也只是模拟, 性能与一致性都会变差。

写入后不再修改的内容(日志、image、backup、model weight)适合 object storage; 持续修改的内容(working directory、DB file)则不适合。

下个练习将做什么

为本地 S3-compatible server 添加 alias,创建 bucket、上传 object,并通过 prefix 进行整理。把 ETag 与本地 md5 对比以确认其含义,并练习 server-side copy 和指定 Content-Type。