GridFS

关注
义项:MongoDB的分布式文件存储规范
GridFS

GridFS 是 MongoDB 用于存储和检索超过 BSON 文档大小限制(16 MiB)的文件的规范,它把大文件切分为若干数据块,分别写入数据库的集合中。[1] 它并非 MongoDB 服务端的特性,而是由各语言官方驱动共同实现的约定,因而按同一约定写入的文件可以被不同驱动读取。[2] 这一机制使大文件也能随文档数据库一同复制与分片,并支持按范围读取文件的局部内容。

百科 图文
目录
  1. 定义
  2. 原理
  3. 发展历程
  4. 应用
  5. 局限
  6. 参见

定义

GridFS 是一套用于存储和检索超出 BSON 文档大小上限的文件的规范,这个上限为 16 MiB。[1] 规范规定文件不再放入单个文档,而是被切分成若干数据块,每一块作为独立文档保存,因此单个文件的体积不再受单文档上限的约束。[3]

按照驱动侧规范的定义,GridFS 是驱动用来存取超出 16 MiB 的 BSON 二进制数据(类型 x05)的一套约定;写入时文件被拆成数据块,读取时再按记录重新拼合。[2] 它保存的对象既可以是磁盘上的实际文件,也可以是一段连续的大数据或输入流。[2]

原理

GridFS 在一个数据库中以“存储桶”为单位组织文件,桶由成组的集合构成,集合名以桶名为前缀,默认桶名是 fs,对应的两个集合是 fs.files 与 fs.chunks。[1] 存放文件内容的 chunks 集合里,每个文档记录一个数据块,字段包括数据块自身的 _id、指向父文件的 files_id、从 0 开始的分块序号 n,以及载荷 data。[2]

存放元数据的 files 集合中,每个文档对应一个已存文件,主要字段有 _id、以字节计的文件长度 length、每个数据块的大小 chunkSize、上传完成时间 uploadDate,以及可选的 filename、md5 和供应用自用的 metadata。[2] 一个文件应有多少个数据块,可以由 length 与 chunkSize 推算出来。[2]

数据块的默认大小为 255 KiB,文件按此大小切分,仅最后一块的实际大小以需要为准;不超过一个块大小的文件只会产生唯一的末块。[1] 关于 255 KiB 这一取值的由来,规范给出的解释是在 MMAPv1 存储引擎下,这样的块文档正好能够放进服务端预留的 256 KiB 内存区段,从而充分利用填充空间。

为支持高效读取,规范要求 chunks 集合上存在 files_id 与 n 的组合唯一索引,files 集合上存在 filename 与 uploadDate 的组合索引;驱动在首次写入前会检查 files 集合是否为空,若为空且索引不存在则创建索引。[2] 读取时,驱动先从 files 集合取出元数据,再依据其中的信息到 chunks 集合重新拼装出完整文件。[4]

发展历程

GridFS 被设计为一种规范而非服务端功能,MongoDB 服务端没有专门处理 GridFS 的代码,全部工作由客户端驱动完成。[5] 这样安排的好处是,任何遵循同一约定的驱动都能读取其他驱动写入的文件。[5]

在 MongoDB 手册的早期版本中,files 集合里的 chunkSize 默认值曾为 256 KB,自 2.4.10 版本起改为 255 KB。[6] 驱动侧规范随后对这一数据模型做了澄清与整理,并把一部分字段列为废弃。[2]

规范还记录了若干后续调整:2016 年 5 月允许应用自定义文件 id,2016 年 10 月要求驱动能够处理不同的 length 与 chunkSize 数值类型并加入读关注(ReadConcern)配置,2018 年 1 月将 MD5 标记为废弃并提供关闭 MD5 计算的选项,2022 年 1 月要求按客户端操作超时规范施加超时。 MD5 被废弃的原因是该算法为 FIPS 140-2 所禁止,在处于 FIPS 模式的系统上可能无法提供。

应用

使用 GridFS 存取文件有两条途径:一是通过 MongoDB 驱动,二是使用 mongofiles 命令行工具。[1] 驱动侧提供存储桶对象及其上传、下载、重命名等方法,上传既可以从内存数据发起,也可以从输入流发起。[4]

GridFS 适用的场合包括:文件大于 16 MiB;需要在系统中保存数量不受目录条数限制的文件;需要读取大文件的局部而不把整个文件读入内存,例如直接跳到音视频的中段。[1] 借助地理分布的副本集,文件及其元数据还可以随数据库复制自动分散到多个 mongod 实例和设施中。[1]

当所有文件都小于 16 MiB 时,规范建议改用 BinData 数据类型把每个文件存入单个文档,而不必引入 GridFS。[1] 若必须对 chunks 集合分片,应选择能够把同一文件的所有数据块路由到同一分片的片键;files 集合通常较小,一般无需分片。

局限

GridFS 不支持多文档事务。[1] 由于存取过程涉及跨集合的多个文档操作,而 MongoDB 目前无法跨集合原子地完成这些操作,因此无法在避免 GridFS 客户端之间竞态的前提下改动已存储的文件。

如果需要原子地更新整个文件的内容,就不应使用 GridFS;可行的替代做法是为每个文件保留多个版本,在元数据中标记当前版本,上传新版本后以原子操作用来更新表示“最新”状态的字段,再按需删除旧版本。[1]

写操作或删除操作中途失败时,chunks 集合中可能留下 files_id 不再对应任何 files 文档的数据块,这类数据块被称为孤儿块。[2] 此外,规范并不规定驱动在发现文件带有多余数据块时报告错误,驱动可以选择忽略这些多余块。

参见

  • MongoDB —— GridFS 是这套文档数据库中用于存取大文件的规范。

  • BSON —— GridFS 要绕开的正是 BSON 文档 16 MiB 的大小上限。

  • 存储桶 —— GridFS 以桶为单位组织 files 与 chunks 两个集合。

  • 分片 —— GridFS 的 chunks 集合可通过片键在集群中分散存储。

  • 副本集 —— GridFS 的文件与元数据可随副本集复制到多个实例。

  • MD5 —— 曾用于校验 GridFS 中文件完整性的散列算法。

参考资料

  1. GridFS - Database Manual v8.0 [引用日期2026-10-14]
  2. gridfs-spec [引用日期2026-10-14]
  3. 自管理部署的 GridFS [引用日期2026-10-14]
  4. mongodb.ac.cn 上的网页 [引用日期2026-10-14]
  5. github.com 上的网页 [引用日期2026-10-14]
  6. GridFS Reference¶ [引用日期2026-10-14]
词条评价
词条统计

浏览次数:3 次

阅读量:0 次 · 阅读完成量:0 次

最近更新:2026-10-13T21:21:05Z

历史版本

本条目引用的词条
MongoDB BSON 存储桶 分片 副本集 MD5