未加星标

GridFS 基于 MongoDB 的分布式文件存储系统

字体大小 | |
[数据库(综合) 所属分类 数据库(综合) | 发布者 店小二03 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

GridFS 基于MongoDB的分布式文件存储系统

什么是GridFS

GridFS是一种将大型文件存储在MongoDB的文件规范。所有官方支持的驱动均实现了GridFS规范。GridFS是MongoDB中的一个内置功能,可以用于存放文件。

为什么要使用GridFS

问题1:我之前将文件上传到文件系统中,比如通过FTP上传到文件服务器。并将文件地址存储到mysql数据库,我觉得这个方式挺好的呀,为什么要使用GridFS?

答:文件系统到了后期会变的很难管理,同时不利于扩展,此外我想做分布式文件系统也显得不那么容易。而GridFS却正好相反,它基于MongoDB的文件系统,便于管理和扩展。

问题2:普通文件系统对于大文件处理比较麻烦,需要考虑文件系统自身的限制,GridFS提供了什么好方案?

答:GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/块,每块chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。这一点对于很大的内容文件非常有用。此外,GridFS和MongoDB的分片使得你的文件可以分布到多个服务器上,而且没有增加操作的复杂性。

问题3:我可以直接把文件的二进制流存到MongoDB么?

答: MongoDB默认的文件大小上限为16MB。所以,超过这个大小是有问题的。如果你的文件,比如图片、音频、视频等超过了16MB,那么你就应该使用GridFS。

GridFS 的两个集合

GridFS 使用两个集合来存储一个文件:fs.files与fs.chunks。我们可以使用下面命令来进行查看。

show collections

fs.files集合包含了文件的元数据。我们使用命令来查看

db.fs.files.findOne();

以下是刚上传文件的元数据信息的 fs.files 集合文档

{ "_id" : ObjectId("57fb553ac7fa9102e0000001"), "chunkSize" : 261120, "uploadDate" : ISODate("2016-10-10T08:45:50.051Z"), "length" : 1.53513e+008, "md5" : "9222e097e624800fdd9bfb568169ccad", "filename" : "E:/jdk-7u79-linux-x64.tar.gz" }

fs.chunks集合则存储实际的以256KB尺寸进行分割的文件块。如果你有分片的集合,那么文件块会分布到多台服务器上。

db.fs.chunks.getIndexes();

以下是刚上传文件的fs.chunks 集合文档

{ "0" : { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "gridfs.fs.chunks" }, "1" : { "v" : 1, "key" : { "files_id" : 1, "n" : 1 }, "name" : "files_id_1_n_1", "ns" : "gridfs.fs.chunks" } } GridFS 基本操作 上传文件

我们使用GridFS的put命令来存储一个文件。首先,调用MongoDB安装目录下bin的mongofiles.exe工具。然后,打开命令提示符,进入到MongoDB的安装目录的bin目录中,找到mongofiles.exe,并输入下面的代码:

mongofiles.exe -d gridfs put E:\elasticsearch-1.7.0.zip

参数说明, d 指定数据库gridfs

列出清单

使用以下命令来查看数据库中文件的文档

db.fs.files.find()

返回以下内容

/* 1 */ { "_id" : ObjectId("57fb553ac7fa9102e0000001"), "chunkSize" : 261120, "uploadDate" : ISODate("2016-10-10T08:45:50.051Z"), "length" : 1.53513e+008, "md5" : "9222e097e624800fdd9bfb568169ccad", "filename" : "E:/jdk-7u79-linux-x64.tar.gz" } /* 2 */ { "_id" : ObjectId("57fb6c49c7fa9135d4000001"), "chunkSize" : 261120, "uploadDate" : ISODate("2016-10-10T10:24:09.654Z"), "length" : 3.17848e+007, "md5" : "882013a3d205289dddce22c904d3c476", "filename" : "E:\\elasticsearch-1.7.0.zip" } 查找文件

可以看到 fs.chunks 集合中所有的区块,以下我们得到了文件的 _id 值,我们可以根据这个 _id 获取区块(chunk)的数据。

db.fs.chunks.find({files_id:ObjectId('57fb553ac7fa9102e0000001')});

以上实例中,查询返回了 50 个文档的数据,意味着文件被存储在50个区块中。

下载文件

我们使用GridFS的get命令来下载一个文件。

mongofiles.exe -d gridfs get E:\elasticsearch-1.7.0.zip Java 操作 GridFS

注意,以下是一个简单的入门案例,不适用于实际场景,实际场景需要考虑异常处理、IO流关闭、日志处理等。

使用的Maven版本

<dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.2.2</version> </dependency>

公共方法

public MongoDatabase mongoDatabase() throws Exception{ MongoClient mongoClient = new MongoClient(mongoHost, mongoPort); return mongoClient.getDatabase(dbName); } 上传文件 @Test public void upload() throws Exception { // 获取文件流 File file = new File("E:/zookeeper-3.4.8.tar.gz"); InputStream in = new FileInputStream(file); // 创建一个容器,传入一个`MongoDatabase`类实例db GridFSBucket bucket = GridFSBuckets.create(mongoDatabase()); // 上传 ObjectId fileId = bucket.uploadFromStream(UUID.randomUUID().toString(), in); System.out.println("上传完成。 文件ID:"+fileId); } 查找文件 @Test public void findOne() throws Exception { // 获取文件ID String objectId = "57fbaffcec773716ecc54ef4"; // 创建一个容器,传入一个`MongoDatabase`类实例db GridFSBucket bucket = GridFSBuckets.create(mongoDatabase()); // 获取内容 GridFSFindIterable gridFSFindIterable = bucket.find(Filters.eq("_id", new ObjectId(objectId))); GridFSFile gridFSFile = gridFSFindIterable.first(); System.out.println("filename: " + gridFSFile.getFilename()); } 下载文件 @Test public void download() throws Exception { // 获取文件ID String objectId = "57fbaffcec773716ecc54ef4"; // 获取文件流 File file = new File("D:/zookeeper-3.4.8.tar.gz"); // 创建一个容器,传入一个`MongoDatabase`类实例db GridFSBucket bucket = GridFSBuckets.create(mongoDatabase()); // 创建输出流 OutputStream os = new FileOutputStream(file); // 下载 bucket.downloadToStream(new ObjectId(objectId), os); System.out.println("下载完成。"); } 删除文件 @Test public void delete() throws Exception { // 获取文件ID String objectId = "57fbaffcec773716ecc54ef4"; // 创建一个容器,传入一个`MongoDatabase`类实例db GridFSBucket bucket = GridFSBuckets.create(mongoDatabase()); // 删除 bucket.delete(new ObjectId(objectId)); System.out.println("删除完成。"); } 总结

GridFS是一种大型文件存储方式之一,有其一定的使用场景,务必根据实际场景选择技术方案。

现在主流的文件存储方案,例如云存储服务,以amazon的s3云服务,七牛云存储都是不错的选择。此外,例如还有阿里开源的tair等键值结构数据的解决方案。

本文数据库(综合)相关术语:系统安全软件

分页:12
转载请注明
本文标题:GridFS 基于 MongoDB 的分布式文件存储系统
本站链接:http://www.codesec.net/view/481591.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(30)