MongoDB基于GridFS实现文件的分布式存储

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介:

GridFS是一种在MongoDB中存储大二进制文件的机制。使用GridFS存文件有如下几个原因:

利用Grid可以简化需求。要是已经用了MongoDB,GridFS就可以不需要使用独立文件存储架构。


GridFS会直接利用业已建立的复制或分片机制,所以对于文件存储来说故障恢复和扩展都很容易。


GridFS可以避免用于存储用户上传内容的文件系统出现的某些问题。例如,GridFS在同一个目录下放置大量的文件是没有任何问题的。


GridFS不产生磁盘碎片,因为MongoDB分配数据文件空间时以2GB为一块。


使用场景:如果你的系统有如下情景:

1) 有大量的上传图片(用户上传或者系统本身的文件发布等)

2) 文件的量级处于飞速增长,有可能打到单机操作系统自己的文件系统的查询性能瓶颈,甚至超过单机硬盘的扩容范围.

3) 文件的备份(不适用gridfs这种三方也可以做,但是不尽方便),文件系统访问的故障转移和修复..

4) 文件的索引,存储除文件本身以外还需要关联更多的元数据信息(比如,不仅仅存储文件,还要保存一些文件的发布式作者/发布时间/文件tag属性等等自定义信息)并且需要索引的...

5) 基于4),对文件的分类模糊,如果采用操作系统的文件系统,文件夹分类关系混乱或者无法分类时..

6) 当前系统是基于web的,对图片的访问根据url了规则路由的..(普通文件系统也可以)

7) 文件尺寸较小,而且众多,且文件有可能被迁移/删除等..


在Mongodb中以GridFSB方式存放文件有两种方式:

1、命令行方式mongofiles 2、客户端驱动编程 

1、命令行方式mongofiles

mongofiles命令行下向Mongodb数据库中插入文件数据。

mongofiles  -host 127.0.0.1:27017 -d  mydb  put  文件名


 向数据库mydb中插入一个文件,其中put为命令,表示向Mongodb中上传文件,get、delete分别表示取得文件和删除文件。


      执行 db.fs.files.find()即可看到GridFS中的文件列表.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mongo自带有一个实现mongofliles,基本操作如下:
列出所有文件:
mongofiles list
上传一个文件:
mongofiles put xxx.txt
下载一个文件:
mongofiles  get  xxx.txt
查找文件:
mongofiles search xxx  //会查找所有文件名中包含“xxx”的文件
mongofiles list xxx  //会查找所有文件名以“xxx”为前缀的文件
参数说明:
–d 指定数据库 ,默认是fs,Mongofiles list –d testGridfs
-u –p 指定用户名,密码
-h 指定主机
-port 指定主机端口
-c 指定集合名,默认是fs
-t 指定文件的MIME类型,默认会忽略

2、使用API来存取文件


   我一般用python调用pymongo管理mongodb的聚集

   这个是国外的一篇pymongo管理gridfs的文档,写的还行。

http://blog.pythonisito.com/2012/05/gridfs-mongodb-filesystem.html


很多时候我们可以搭配nginx用,让nginx直接读取gridfs的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
安装nginx-gridfs
wget https: //download.github.com/mdirolf-nginx-gridfs-v0.8-0-gb5f8113.tar.gz
tar –zxvf mdirolf-nginx-gridfs-v0. 8 - 0 -gb5f8113.tar.gz
mv mdirolf-nginx-gridfs-v0. 8 - 0 -gb5f8113 mdirolf-nginx-gridfs-v0. 8
wget https: //download.github.com/mongodb-mongo-c-driver-v0.3-0-g74cc0b8.tar.gz
tar –zxvf mongodb-mongo-c-driver-v0. 3 - 0 -g74cc0b8.tar.gz
mv mongodb-mongo-c-driver-v0. 3 - 0 -g74cc0b8/* mdirolf-nginx-gridfs-v0. 8 /mongo-c-driver
rm –rf mongodb-mongo-c-driver-v0. 3 - 0 -g74cc0b8
安装nginx,指定nginx-gridfs目录与nginx联合编译
wget http: //nginx.org/download/nginx-1.0.1.tar.gz
tar –zxvf nginx- 1.0 . 1 .tar.gz
cd nginx- 1.0 . 1
./configure --prefix=/usr/local/nginx -- with -openssl=/usr/ include /openssl -- with -http_stub_status_module --add-module=/home/cdh/Downloads/mdirolf-nginx-gridfs
make –j8
sudo make install –j8
配置nginx-gridfs
location /pics/ {
     gridfs pics
               field=filename
               type=string;
     mongo  127.0 . 0.1 : 27017 ;
}
gridfs:nginx识别插件的关键字
pics:db名
[root_collection]: 选择collection,如root_collection=blog, mongod就会去找blog.files与blog.chunks两个块,默认是fs
[field]:查询字段,保证mongdb里有这个字段名,支持_id, filename, 可省略, 默认是_id
[type]:解释field的数据类型,支持objectid,  int , string, 可省略, 默认是 int
[user]:用户名, 可省略
[pass]:密码, 可省略
mongo:mongodb url
http: //localhost/pics/photo.jpg 能下载图片就说明成功了



gridfs 都是应用到偏海量,又不到海量的文件需求场景下的,不然咱们也不会花这么多功夫来搞这个了。



在这种需求下,可以用分片和主从把压力分切开。

093220200.png



093917766.jpg


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mkdir -p /data/shard/s0
mkdir -p /data/shard/s1
mkdir -p /data/shard/log
mkdir -p /data/shard/config
#启动shard server
./mongod --shardsvr --port  20000  --dbpath /data/shard/s0 --fork --logpath /data/shard/log/s0.log --directoryperdb
./mongod --shardsvr --port  20001  --dbpath /data/shard/s1 --fork --logpath /data/shard/log/s1.log --directoryperdb
#启动配置服务器config server
./mongod --configsvr --port  30000  --dbpath /data/shard/config --fork --logpath /data/shard/log/config.log --directoryperdb
#启动route server mongos
mongos --port  40000  --configdb localhost: 30000  --fork --logpath /data/shard/log/route.log --chunkSize  1
#添加分片
./mongo admin --port  40000   #链接mongos
db.runCommand({addshard: "localhost:20000" }) #添加分片 1
db.runCommand({addshard: "localhost:20001" }) #添加分片 2
db.runCommand({enablesharding: "test" })  #设置test库开启分片
db.runCommand({shardcollection: "test.users" ,key:{_id: 1 }}) #设置test.users集合分片和分片的主键
#验证sharding
use  test
#插入 50 万数据
for ( var  i= 1 ;i<= 500000 ;i++) db.users.insert({age:i,name: "zx" ,addr: "beijing" ,country: "china" })
db.users.stats() #查看users的分片情况






 本文转自 rfyiamcool 51CTO博客,原文链接:http://blog.51cto.com/rfyiamcool/1219848,如需转载请自行联系原作者


相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
5月前
|
存储 NoSQL Shell
如何将阿里云WiredTiger引擎的MongoDB物理备份文件恢复至自建数据库
数据库操作一直是一个比较敏感的话题,动不动“删库跑路”,可见数据库操作对于一个项目而言是非常重要的,我们有时候会因为一个游戏的严重bug或者运营故障要回档数据库,而你们刚好使用的是阿里云的Mongodb,那么这篇文章将给你提供一个思路(或许你按照阿里云官网的文档一顿操作下来,并不是那么顺利,有一些报错,无法登录...)
|
6月前
|
存储 JSON NoSQL
95分布式电商项目 - MongoDB 简介
95分布式电商项目 - MongoDB 简介
36 0
|
存储 NoSQL 安全
MongoDB分布式存储数据库系列(三)------用户与权限管理
Mongodb 作为时下最为热门的数据库,那么其安全验证也是必不可少的
66 0
|
存储 NoSQL 安全
|
存储 SQL JSON
MongoDB分布式存储数据库系列(一)------简介
MongoDB 是一个基于分布式文件存储的数据库。由 C++语言编写。在为 WEB 应用提供可扩展的高性能数据存储解决方案。
176 0
MongoDB分布式存储数据库系列(一)------简介
|
存储 缓存 NoSQL
分布式服务器框架之Servers.Core中 实现Log模块设计 写入MongoDB数据库
游戏服务器中都需要用到Log模块,log模块存在的意义第一个是将log输出到控制台又或者是写入到log文件中,出了BUG方便定位;第二是常用于将用户的数据(例如玩家登录、道具购买量)将这种log统计到数据库中,方便统计用户留存信息、数据分析等。
|
NoSQL MongoDB 数据库
分布式服务器框架之Server.Core库中实现YFUniqueEntity、YFUniqueIDBase 管理MongoDB 自定义Id的自增
YFUniqueEntity是数据库中的结构,GetUniqueID函数中会根据Type和自增步长去数据库中寻找该类型的当前ID是多少,然后会用当前的Id去加上步长,把更新后的新ID插入到MongoDB中记录着ID的那张表里。
|
NoSQL MongoDB
分布式服务器框架之Servers.Core库中实现 MongoEntityBase 实现阻塞 异步对MongoDB的增删改查
YFMongoDBModelBase类是个模板类,对模板参数进行了约束YFMongoEntityBase,必须要继承YFMongoEntityBase
|
JSON NoSQL MongoDB
分布式服务器框架之Servers.Core库中实现MongoDB的ObjectId和Json转换
分布式服务器框架之Servers.Core库中实现MongoDB的ObjectId和Json转换
|
SQL NoSQL MongoDB
分布式服务器框架之Servers.Core库中实现MongoDB对象实体类 管理对象ID
MongoDB中的ID是一个hash码,和传统的关系数据库相比MongoDB没有办法实现ID的自增,如果需要ID自增的话,所以要自己管理ID,并且把对应类型的ID写入到一个专门的Collection(其实就是Sql中的Table)里面去,每次创建新对象的时候,都要取到该类型当前的ID,然后在这个基础上+1,比如当前是角色的ID是1,又创建了一个新的角色,要在原来的基础上+1 ID=2。今天先把MongoDB的对象实体基类实现了。