专栏首页Hadoop数据仓库浅尝辄止MongoDB:GridFS

浅尝辄止MongoDB:GridFS

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wzy0623/article/details/82894835

一、为什么使用GridFS

GridFS是MongoDB的一个子模块,使用GridFS可以基于MongoDB来持久存储文件,并且支持分布式应用(文件分布存储和读取)。作为MongoDB中二进制数据存储在数据库中的解决方案,通常用来处理大文件,对于MongoDB的BSON格式的数据(文档)存储有尺寸限制,最大为16M。但是在实际系统开发中,上传的图片或者文件可能尺寸会很大,此时我们可以借用GridFS来辅助管理这些文件。

GridFS不是MongoDB自身特性,只是一种将大型文件存储在MongoDB的文件规范,所有官方支持的驱动均实现了GridFS规范。GridFS制定大文件在数据库中如何处理,通过开发语言驱动来完成、通过API接口来存储检索大文件。

GridFS的主要特性可以简单归纳为:

  1. 用MongoDB存储大文件。
  2. 突破MongoDB单个文档最大16MB的限制。
  3. 可以访问部分文件,而不用向内存中加载全部文件,从而保持高性能。
  4. 文件和元数据自动同步。

二、GridFS存储原理

http://rdc.hundsun.com/portal/article/703.html

三、使用GridFS

1. 准备测试文件

cat /usr/share/dict/words > /tmp/dictionary

2. 查看MongoDB中的文件

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin list
2018-09-29T09:47:04.391+0800    connected to: localhost
[mongodb@hdp4~]$

list命令将列出数据库中的所有文件,当前数据库中没有任何文件。mongofiles是一个概念验证工具,主要用于学习和测试,而不应该在自己的应用中使用。

3. 将词典文件添加到数据库

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin put /tmp/dictionary
2018-09-29T09:52:27.928+0800    connected to: localhost
2018-09-29T09:52:28.059+0800    added file: /tmp/dictionary

[mongodb@hdp4~]$

4. 再次查看MongoDB中的文件

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin list
2018-09-29T09:53:36.372+0800    connected to: localhost
/tmp/dictionary    4953680
[mongodb@hdp4~]$

返回了词典文件及其大小,这些信息来自于files集合。MongoDB将文件拆分为块存储,默认的块大小为256K,可通过chunksize参数修改,但不能超过16MB的限制。put命令的返回信息中还包括文件上传时间戳,存储该文件在MongoDB中的创建时间。

5. 存储重名文件

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin put /tmp/dictionary
2018-09-29T09:58:59.894+0800    connected to: localhost
2018-09-29T09:58:59.976+0800    added file: /tmp/dictionary

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin list
2018-09-29T09:59:03.918+0800    connected to: localhost
/tmp/dictionary    4953680
/tmp/dictionary    4953680
[mongodb@hdp4~]$

再put一遍同一文件,MongoDB中存储了两个同样的文件,它们的元数据一致,除了_id键。MongoDB提供了md5哈希算法,但GridFs不会自动处理md5值相同的文件。也就是说,同一个文件进行两次put命令,将会在GridFS中对应两个不同的存储,对于存储来说,这是一种浪费。对于md5相同的文件,如果想要在GridFS中只有一个存储,需要通过API进行扩展处理。

6. 在MongoDB中查看数据

> use test;
switched to db test
> show collections;
fs.chunks
fs.files
> db.fs.files.find();
{ "_id" : ObjectId("5baee3102785bf92e10d44cb"), "chunkSize" : 261120, "uploadDate" : ISODate("2018-09-29T02:27:29.073Z"), "length" : 4953680, "md5" : "15a189ff6eacf1796d56e2156d48d69a", "filename" : "/tmp/dictionary" }
{ "_id" : ObjectId("5baee3122785bf92ec0c8f6f"), "chunkSize" : 261120, "uploadDate" : ISODate("2018-09-29T02:27:30.540Z"), "length" : 4953680, "md5" : "15a189ff6eacf1796d56e2156d48d69a", "filename" : "/tmp/dictionary" }
> db.fs.chunks.find({},{"data":0});
{ "_id" : ObjectId("5baee3102785bf92e10d44cc"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 0 }
{ "_id" : ObjectId("5baee3102785bf92e10d44cf"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 3 }
{ "_id" : ObjectId("5baee3102785bf92e10d44cd"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 1 }
{ "_id" : ObjectId("5baee3102785bf92e10d44ce"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 2 }
{ "_id" : ObjectId("5baee3102785bf92e10d44d0"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 4 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d1"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 5 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d2"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 6 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d3"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 7 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d4"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 8 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d5"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 9 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d6"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 10 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d7"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 11 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d8"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 12 }
{ "_id" : ObjectId("5baee3112785bf92e10d44d9"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 13 }
{ "_id" : ObjectId("5baee3112785bf92e10d44da"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 14 }
{ "_id" : ObjectId("5baee3112785bf92e10d44db"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 15 }
{ "_id" : ObjectId("5baee3112785bf92e10d44dc"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 16 }
{ "_id" : ObjectId("5baee3112785bf92e10d44dd"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 17 }
{ "_id" : ObjectId("5baee3112785bf92e10d44de"), "files_id" : ObjectId("5baee3102785bf92e10d44cb"), "n" : 18 }
{ "_id" : ObjectId("5baee3122785bf92ec0c8f70"), "files_id" : ObjectId("5baee3122785bf92ec0c8f6f"), "n" : 0 }
Type "it" for more
>

数据存储在test数据库中,在该数据库中生成了fs.files和fs.chunks两个集合。files存储文件元数据信息,chunks存储文件中的数据。7. 使用搜索命令 (1)上传一个新文件

[mongodb@hdp4~]$cp /tmp/dictionary /tmp/hello_world
[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin put /tmp/hello_world
2018-09-29T10:33:15.332+0800    connected to: localhost
2018-09-29T10:33:15.484+0800    added file: /tmp/hello_world

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin list
2018-09-29T10:33:26.149+0800    connected to: localhost
/tmp/dictionary    4953680
/tmp/dictionary    4953680
/tmp/hello_world    4953680
[mongodb@hdp4~]$

(2)用search命令搜索文件名

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin search hell
2018-09-29T10:35:07.059+0800    connected to: localhost
/tmp/hello_world    4953680
[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin search ict
2018-09-29T10:35:13.385+0800    connected to: localhost
/tmp/dictionary    4953680
/tmp/dictionary    4953680
[mongodb@hdp4~]$

8. 删除MongoDB中的文件

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin delete /tmp/dictionary
2018-09-29T10:37:38.140+0800    connected to: localhost
2018-09-29T10:37:38.186+0800    successfully deleted all instances of '/tmp/dictionary' from GridFS

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin list
2018-09-29T10:37:40.884+0800    connected to: localhost
/tmp/hello_world    4953680
[mongodb@hdp4~]$

使用delete命令有两点需要注意:

  • 该命令基于文件名删除文件,因此将删除所有同名文件。
  • MongoDB不会释放已经占用的硬盘空间。即使删除db中的集合MongoDB也不会释放磁盘空间。同样,如果使用GridFS存储文件,从GridFS存储中删除无用的垃圾文件,MongoDB依然不会释放磁盘空间的。这会造成磁盘一直在消耗,而无法回收利用的问题。

此时数据库中只存储了/tmp/hello_world一个文件:

> use test
switched to db test
> show collections;
fs.chunks
fs.files
> db.fs.files.find();
{ "_id" : ObjectId("5baee46b2785bf94c31b08ff"), "chunkSize" : 261120, "uploadDate" : ISODate("2018-09-29T02:33:15.505Z"), "length" : 4953680, "md5" : "15a189ff6eacf1796d56e2156d48d69a", "filename" : "/tmp/hello_world" }
>

9 从MongoDB中获取文件

[mongodb@hdp4~]$mongofiles -u "wxy" -p "rockey" --authenticationDatabase admin get /tmp/hello_world
2018-09-29T10:46:04.095+0800    connected to: localhost
2018-09-29T10:46:04.211+0800    finished writing to /tmp/hello_world

[mongodb@hdp4~]$

该例故意包含了一个错误。因为指定了希望读取文件的绝对文件名,mongofiles将把数据写入到含有相同名字和路径的文件中。事实上,该命令将复写原始的/tmp/hello_world文件。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Windows下Apache应用环境塔建安全设置(目录权限设置)

    目的:为Apache,php配置受限制的用户权限。保护系统安全。需要的朋友可以参考下。

    习惯说一说
  • 设计模式- 单例模式(Singleton Pattern)

    易兒善
  • MySQL 中 update 修改数据与原数据相同会再次执行吗?

    良月柒
  • Spark SQL从入门到精通

    熟悉spark sql的都知道,spark sql是从shark发展而来。Shark为了实现Hive兼容,在HQL方面重用了Hive中HQL的解析、逻辑执行计划...

    Spark学习技巧
  • 记住:永远不要在 MySQL 中使用 UTF-8

    最近我遇到了一个 bug,我试着通过 Rails 在以“utf8”编码的 MariaDB 中保存一个 UTF-8 字符串,然后出现了一个离奇的错误:

    芋道源码
  • Spring Boot 最流行的 16 条实践解读!

    Spring Boot项目本身使用和集成了大量的开源项目,它帮助我们维护了这些第三方依赖。但是也有一部分在实际项目使用中并没有包括进来,这就需要我们在项目中自己...

    芋道源码
  • 第三方账户登录--github

    使用node+express创建项目,可以参考这篇文章 node+express项目

    RtyXmd
  • 手把手教你用R下载TCGA数据:RTCGAToolbox

    各位朋友,大家好,今天,我们分享TCGA数据的最后一个R包,RTCGAToolbox。TCGA数据量庞大,数据种类丰富,分析方法复杂,对于大部分研究人员来说,从...

    微点
  • 分布式系统关注点(18)——「缓存穿透」和「缓存雪崩」到底啥区别?

    有句话说得好,欲要使其毁灭,先要使其疯狂。当你沉浸在缓存所带来的系统tps飙升的喜悦中时,使你系统毁灭的种子也已经埋在其中。

    Zachary_ZF
  • 使用模式构建:子集模式

    在多年前,第一代PC拥有高达256KB的RAM和两个5.25英寸的软盘驱动器。没有硬盘,因为在当时它们极为昂贵。这些限制导致在处理大量(对那时来说)数据时由于内...

    MongoDB中文社区

扫码关注云+社区

领取腾讯云代金券