为什么没有文件夹
一句话总结
object storage 中没有目录。img/2026/logo.png 只是一个包含 slash 的长 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。