S3 是文件,但不是文件系统

Amazon S3 经常被当作文件系统使用,但评论者强调它本质上是对象/键值存储,语义与传统文件系统截然不同:没有真正的目录、不能原地修改、重命名不是原子操作,而且基于前缀的列举也很慢。之所以重要,是因为如果不加适配层就把 POSIX 导向的软件(如传统数据库或 Hadoop)直接跑在 S3 上,往往会导致性能很差、出现微妙的一致性问题,以及围绕“文件夹”的混乱行为。许多参与者也描述了 S3 的优势——极高的持久性、可扩展性,以及对不可变 blob 的简单性——并指出专门的层(EMRFS、Delta/Iceberg/Hudi、rclone VFS、JuiceFS、类似 Aurora 的架构)才是当需要文件系统式特性时弥合差距的正确方式。

S3 是什么(以及不是什么)

  • 广泛共识:S3 是对象存储 / 键值存储,不是传统文件系统。
  • 核心模型:键 → 对象的扁平映射;键是不可解析的字符串,操作是对整个对象进行 GET/PUT/DELETE。
  • POSIX 风格语义(inode、作为一等对象的目录、部分写入、原子重命名)从设计上就不存在。
  • 也有人认为从广义上说,S3 仍算是“一种文件系统”(“管理文件的系统”),但另一些人坚持这样会稀释这个术语,并让用户产生错误预期。

“文件夹”和路径语义

  • S3 没有真正的目录。控制台里的“文件夹”只是基于键前缀的 UI 包装,有时通过 0 字节的“标记”对象来实现。
  • 后果:
    • 你可以同时拥有 dirdir/filedir//file 这样的键;斜杠对 S3 来说并不特殊。
    • 当删除最后一个带有该前缀的对象时,空的“文件夹”就会消失。
    • 重命名一个“文件夹”需要复制并删除该前缀下的每个对象(O(对象数量),且不是原子操作)。

操作、性能与列举

  • 不支持原地修改或追加;必须重新上传修改后的内容,或者在更高层进行分块。
  • 复制和重命名通过 copy+delete 实现,其成本和延迟会随对象大小增长。
  • 列举是一个重大的语义和性能差异:
    • S3 按前缀和字典序列出,并支持分页;对于基于前缀的扫描和分区,效率可以非常高。
    • 递归的、POSIX 风格的目录遍历很慢,需要大量顺序的 list 调用;删除或清空大型 bucket 可能既昂贵又复杂。

在 S3 上运行数据库和文件系统层

  • 直接在 S3 上运行传统数据库通常被认为不合适:延迟高、缺少部分写入、没有原子的“若不存在则写入”。
  • 成功的模式:
    • 只追加或将文件视为不可变分片的系统(例如分析引擎、像 Delta/Iceberg/Hudi 这样的表格式)。
    • 使用 S3 作为数据平面、同时配备独立且强一致的元数据/索引层的架构(例如在 S3 上使用 WAL,再配合本地缓存的数据库,或外部元数据服务)。
    • FUSE 和 VFS 层(例如 rclone、自定义文件系统)通过本地缓存、分块以及在别处管理元数据来模拟 POSIX——有用,但复杂且容易泄露抽象。

持久性、成本与替代方案

  • S3 的持久性受到高度赞扬;被描述为业界领先,使用大量校验和和复制,但没有引用第三方、类似 Jepsen 的验证。
  • S3 通常被认为适合大规模、冷数据且成本较低;也有人指出存在更便宜的对象存储,但可能会以可靠性或功能为代价。
  • 若需要真正的文件系统语义和低延迟,评论者会指向 EBS/EFS/FSx 或本地文件系统;若想要“像 S3 但更简单”的本地方案,则会建议对象存储服务器或自定义层。