使用 GridFS 在 MongoDB 中存储图像是否有效?
Is it efficient to store images inside MongoDB using GridFS?
我知道怎么做了,不知道有没有效果。据我所知,MongoDB 拥有非常高效的集群,我可以灵活地控制集合及其驻留的服务器。唯一的问题是文件的大小和通过 MongoDB.
访问它们的速度
我应该探索类似 Apache Hadoop 的东西,还是如果我智能集群 MongoDB,我会得到类似的访问速度结果吗?
最好的做法是将图片上传到某个地方(您的服务器或云端),然后只将图片 url
存储在 MongoDB
。
GridFS 是为了方便而提供的,它并非旨在成为最终的二进制 blob 存储平台。
MongoDB 对其存储的每个文档施加 16 MB 的限制。例如,这不同于许多允许存储更大值的关系数据库。
由于许多应用程序处理大型二进制 blob,MongoDB 解决此问题的方法是 GridFS,其大致工作方式如下:
- 对于每个要插入的 blob,元数据文档都会插入到元数据集合中。
- 然后,实际的 blob 被分成 16 MB 的块,并作为文档序列上传到 blob 集合中。
- MongoDB 驱动程序提供写入和读取 blob 和元数据的帮助程序。
因此,乍一看,问题已解决——应用程序可以直接存储任意大的 blob。然而,深入挖掘,GridFS 具有以下 issues/limitations:
- 在服务器端,存储 blob 块的文档不会与其他文档分开存储。因此,它们与实际文档竞争缓存 space。同时具有内容文档和 blob 的数据库的性能可能比仅具有内容文档的数据库差。
- 同时,由于 blob 块的存储方式与内容文档相同,因此存储它们通常 昂贵 。比如S3比EBS存储便宜很多,GridFS会把所有数据都放在EBS上。
- 据我所知,不支持并行写入或并行读取 blob(writing/reading 同一 blob 的多个块)。这原则上可以在 MongoDB 驱动程序或应用程序中实现,但据我所知,任何驱动程序都没有开箱即用。当 blob 很大时,这会限制 I/O 性能。
- 同样,如果读取或写入失败,则必须重新读取或重写整个 blob,而不是仅仅丢失的片段。
尽管存在这些问题,GridFS 对于许多用例来说可能是一个很好的解决方案:
- 如果总体数据量不是很大,缓存的负面影响是有限的。
- 如果大多数 blob 都可以放在一个文档中,那么它们的存储应该非常有效。
- 对 blob 进行备份,并与数据库中的内容文档一起传输,提高数据一致性并降低数据风险 loss/inconsistencies。
无论如何,我做了一点调查。简短的结论是:如果你需要存储用户头像,你可以使用 MongoDB,但前提是它是单个头像(你不能在 MongoDB 中存储很多 blob)并且如果你需要存储视频或者只有很多大文件,那么你需要像 CephFS 这样的东西。
为什么我这么认为?问题是,当我在慢速实例上使用 MongoDB 和媒体文件进行测试时,重达 10mb(通常约为 1 兆字节)的文件返回时间长达 3000 毫秒。那是一段无法接受的漫长时间。当有很多文件(100+)时,它会变得很痛苦。真的很痛苦。
Ceph 专为存储文件而设计。存储数 PB 的信息。这就是需要的。
你如何在实际项目中实现这一点?如果您使用 MongoDB(Mongoose) 的 OOP 实现,您只需向访问 Ceph 的数据库对象添加方法并执行您需要的操作。您可以创建“加载文件”、“删除文件”、“计数数量”等方法,然后像往常一样将它们一起使用。不要忘记维护 Ceph,根据需要添加服务器,一切都会完美运行。文件本身应该只能通过您的网络服务器访问,而不是直接访问,即当用户需要提供文件时,网络服务器应该向 Ceph 发出请求,并且 return Ceph 对用户的响应。
我希望我帮助的不仅仅是我自己。我会将 Ceph 添加到我的标签中。祝你好运!
我知道怎么做了,不知道有没有效果。据我所知,MongoDB 拥有非常高效的集群,我可以灵活地控制集合及其驻留的服务器。唯一的问题是文件的大小和通过 MongoDB.
访问它们的速度我应该探索类似 Apache Hadoop 的东西,还是如果我智能集群 MongoDB,我会得到类似的访问速度结果吗?
最好的做法是将图片上传到某个地方(您的服务器或云端),然后只将图片 url
存储在 MongoDB
。
GridFS 是为了方便而提供的,它并非旨在成为最终的二进制 blob 存储平台。
MongoDB 对其存储的每个文档施加 16 MB 的限制。例如,这不同于许多允许存储更大值的关系数据库。
由于许多应用程序处理大型二进制 blob,MongoDB 解决此问题的方法是 GridFS,其大致工作方式如下:
- 对于每个要插入的 blob,元数据文档都会插入到元数据集合中。
- 然后,实际的 blob 被分成 16 MB 的块,并作为文档序列上传到 blob 集合中。
- MongoDB 驱动程序提供写入和读取 blob 和元数据的帮助程序。
因此,乍一看,问题已解决——应用程序可以直接存储任意大的 blob。然而,深入挖掘,GridFS 具有以下 issues/limitations:
- 在服务器端,存储 blob 块的文档不会与其他文档分开存储。因此,它们与实际文档竞争缓存 space。同时具有内容文档和 blob 的数据库的性能可能比仅具有内容文档的数据库差。
- 同时,由于 blob 块的存储方式与内容文档相同,因此存储它们通常 昂贵 。比如S3比EBS存储便宜很多,GridFS会把所有数据都放在EBS上。
- 据我所知,不支持并行写入或并行读取 blob(writing/reading 同一 blob 的多个块)。这原则上可以在 MongoDB 驱动程序或应用程序中实现,但据我所知,任何驱动程序都没有开箱即用。当 blob 很大时,这会限制 I/O 性能。
- 同样,如果读取或写入失败,则必须重新读取或重写整个 blob,而不是仅仅丢失的片段。
尽管存在这些问题,GridFS 对于许多用例来说可能是一个很好的解决方案:
- 如果总体数据量不是很大,缓存的负面影响是有限的。
- 如果大多数 blob 都可以放在一个文档中,那么它们的存储应该非常有效。
- 对 blob 进行备份,并与数据库中的内容文档一起传输,提高数据一致性并降低数据风险 loss/inconsistencies。
无论如何,我做了一点调查。简短的结论是:如果你需要存储用户头像,你可以使用 MongoDB,但前提是它是单个头像(你不能在 MongoDB 中存储很多 blob)并且如果你需要存储视频或者只有很多大文件,那么你需要像 CephFS 这样的东西。
为什么我这么认为?问题是,当我在慢速实例上使用 MongoDB 和媒体文件进行测试时,重达 10mb(通常约为 1 兆字节)的文件返回时间长达 3000 毫秒。那是一段无法接受的漫长时间。当有很多文件(100+)时,它会变得很痛苦。真的很痛苦。
Ceph 专为存储文件而设计。存储数 PB 的信息。这就是需要的。
你如何在实际项目中实现这一点?如果您使用 MongoDB(Mongoose) 的 OOP 实现,您只需向访问 Ceph 的数据库对象添加方法并执行您需要的操作。您可以创建“加载文件”、“删除文件”、“计数数量”等方法,然后像往常一样将它们一起使用。不要忘记维护 Ceph,根据需要添加服务器,一切都会完美运行。文件本身应该只能通过您的网络服务器访问,而不是直接访问,即当用户需要提供文件时,网络服务器应该向 Ceph 发出请求,并且 return Ceph 对用户的响应。
我希望我帮助的不仅仅是我自己。我会将 Ceph 添加到我的标签中。祝你好运!