NoSQLMongoDb gridfs-ngnix文件存储方案

  于个系统应用服务端支出中,我们经常会面逢文件存储的题目。
常见的磁盘文件系统,DBMS传统文书流存储。今天我们看一下基于NoSQL数据库MongoDb的贮存方案。笔者环境
以CentOS 6.5,MongoDb 2.6.3,  Nginx-1.4.7
为例,您得了解Linux常用命令。 
预先来回顾一下MongoDb的内文件结构

NoSQL 1

  1. MongoDB在多少存储上按照命名空间来分,一个collection是一个命名空间,一个目录也是一个命名空间
  2. 暨一个命名空间的多少让分为很多只Extent,Extent之间采用对奔链表连接
  3. 当各个一个Extent中,保存了切实可行每一行的数,这些数据也是通过双向链接连接的
  4. 各国一行数存储空间不仅囊括数据占用空间,还可能带有有增大空间,这使得以数码update变大后可以免活动位置
  5. 招来引以BTree结构实现

然后是GridFs的结构

NoSQL 2

GridFS在数据库被,默认使用fs.chunks和fs.files来存储文件。

其中fs.files集合存放文件之音讯,fs.chunks存放文件数量。

一个fs.files集合中之平等长记下内容如下,即一个file的信如下:

1
2
3
4
5
6
7
8
9
10
{
"_id" : ObjectId("4f4608844f9b855c6c35e298"),       //唯一id,可以是用户自定义的类型
"filename" : "CPU.txt",      //文件名
"length" : 778,      //文件长度
"chunkSize" : 262144,    //chunk的大小
"uploadDate" : ISODate("2012-02-23T09:36:04.593Z"), //上传时间
"md5" : "e2c789b036cfb3b848ae39a24e795ca6",      //文件的md5值
"contentType" : "text/plain"     //文件的MIME类型
"meta" : null    //文件的其它信息,默认是没有”meta”这个key,用户可以自己定义为任意BSON对象
}

对应的fs.chunks中的chunk如下:

1
2
3
4
5
6
{
"_id" : ObjectId("4f4608844f9b855c6c35e299"),    //chunk的id
"files_id" : ObjectId("4f4608844f9b855c6c35e298"),  //文件的id,对应fs.files中的对象,相当于fs.files集合的外键
"n" : 0,     //文件的第几个chunk块,如果文件大于chunksize的话,会被分割成多个chunk块
"data" : BinData(0,"QGV...")     //文件的二进制数据,这里省略了具体内容
}

文件存入到GridFS过程中,如果文件大于chunksize,则拿文件分割成多只chunk,再将这些chunk保存至fs.chunks中,最后重复管文件信息存入到fs.files中。

以读取文件的当儿,先据查询的基准,在fs.files中找到一个相当的记录,得到“_id”的值,再按照这价值到fs.chunks中追寻所有“files_id”为“_id”的chunk,并据“n”排序,最后依次读取chunk中“data”对象的情,还原成原本的公文。 

安装Install与配置

1.安装mongoDb

增加MongoDB Repository,不清楚vim,请参考VIM

vim /etc/yum.repos.d/mongodb.repo

如果是64bit的

[mongodb]

name=MongoDB Repository

baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86\_64/

gpgcheck=0

enabled=1

32bit的系统:

[mongodb]

name=MongoDB Repository

baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/i686/

gpgcheck=0

enabled=1

下一场安装,会提示Y/N:

yum install mongo-10gen mongo-10gen-server

启动:

service mongod start

查看状态

service mongod status

停止

service mongod stop

重多,关于3.0上述版本,请参考官网。

2.安装nginx及nginx-gridfs

依赖库、工具

# yum -y install pcre-devel openssl-devel zlib-devel

# yum -y install gcc gcc-c++

下载nginx-gridfs源码

# git clone https://github.com/mdirolf/nginx-gridfs.git

# cd nginx-gridfs

# git checkout v0.8

# git submodule init

# git submodule update

下载nginx源码,编译安装。(高版本支持不好)

# wget http://nginx.org/download/nginx-1.4.7.tar.gz

# tar zxvf nginx-1.4.7.tar.gz

# cd nginx-1.4.7

# ./configure –with-openssl=/usr/include/openssl –add-module style=”color: #9b00d3;”>=../nginx-gridfs/

# make -j8 && make install –j8

只顾蓝色字符配置成相应nginx-gridfs的途径

  1. 配置nginx-gridfs

vim /usr/local/nginx/conf/nginx.conf

于 server 节点中上加 location 节点

location /img/ { 
        gridfs testdb 
        field=filename 
        type=string; 
        mongo 192.168.0.159:27017; 
}

location /files/ { 
        gridfs testdb 
        field=_id 
        type=objectid; 
        mongo 192.168.0.159:27017; 
}

此地我们的mongo服务在IP 192.168.0.159。 
万一无点名 field,默认为 MongoDB 的自增ID,且type为int

安排参数介绍:

gridfs:nginx识别插件的首要字 
testdb: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 

启动nginx服务

# /usr/local/nginx/sbin/nginx

兴许出现: 
Nginx [emerg]: bind() to 0.0.0.0:80 failed (98: Address already in
use)

这可用使用命令关闭占用80端口之次

sudo fuser -k 80/tcp

简言之测试

因此原生的授命执行上污染一个文书

mongofiles put 937910.jpg –local ~/937910_100.jpg –host
192.168.0.159 –port 27017 –db testdb –type jpg

937910.jpg是咱们提前下充斥好一个图纸文件,注意我们从未点名collection,默认是fs

从http://www.robomongo.org/设置robomongo管理工具, 查看刚刚上传的文本

NoSQL 3

末咱们以浏览器访问,如果见到图片就OK了

http://192.168.0.159/img/937910.jpg

对于.net环境下mongodb CSharpDriver  1.10.0 从Nuget: 
Install-Package mongocsharpdriver -Version 1.10.0 
咱使用如下一些代码: 

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
32
33
34
int nFileLen = fileUploadModel.FileBytes.Length;
 
MongoGridFSSettings fsSetting = new MongoGridFSSettings() { Root = CollectionName };
MongoGridFS fs = new MongoGridFS(mongoServer, MongoDatabaseName, fsSetting);
 
//调用Write、WriteByte、WriteLine函数时需要手动设置上传时间
//通过Metadata 添加附加信息
MongoGridFSCreateOptions option = new MongoGridFSCreateOptions();
option.Id = ObjectId.GenerateNewId();
var currentDate = DateTime.Now;
option.UploadDate = currentDate;
option.Aliases = alias;
BsonDocument doc = new BsonDocument();
//文档附加信息存储
if(fileUploadModel.DocExtraInfo!=null&&fileUploadModel.DocExtraInfo.Count>0)
{
    foreach(var obj in fileUploadModel.DocExtraInfo)
    {
        if (!doc.Elements.Any(p => p.Name == obj.Key))
        {
            doc.Add(obj.Key, obj.Value);
        }
    }
}
option.Metadata = doc;
 
//创建文件,文件并存储数据
using (MongoGridFSStream gfs = fs.Create(fileUploadModel.FileName, option))
{
    gfs.Write(fileUploadModel.FileBytes, 0, nFileLen);
    gfs.Close();
}
log.ErrorFormat("附件标识:{0} 文件名:{1} 上传成功", alias, fileUploadModel.FileName);
return option.Id.ToString();

注意,目前gridfs-ngnix不支持_id类型是GUID的,关于ObjectId参考官网,如下图:

NoSQL 4

mongodb产生objectid还有一个又特别的优势,就是mongodb可以经过自身之服务来有objectid,也足以经客户端的驱动程序来来。

哟时候下Gridfs

源于官方2.6.10本子本 手册内容

For documents in a MongoDB collection, you should always use GridFS
for storing files larger than 16 MB.  In some situations, storing
large files may be more efficient in a MongoDB database than on a
system-level filesystem. 

• If your filesystem limits the number of files in a directory, you
can use GridFS to store as many files as needed. 
• When you want to keep your files and metadata automatically synced
and deployed across a number of systems and facilities. When using
geographically distributed replica sets MongoDB can distribute files
and their metadata automatically to a number of mongod instances and 
facilities. 
• When you want to access information from portions of large files
without having to load whole files into memory, you can use GridFS to
recall sections of files without reading the entire file into
memory. 

Do not use GridFS if you need to update the content of the entire file
atomically. As an alternative you can store multiple versions of each
file and specify the current version of the file in the metadata. You
can update the metadata field that indicates “latest” status in an
atomic update after uploading the new version of the file, and later
remove previous versions if needed. 

Furthermore, if your files are all smaller the 16 MB BSON Document
Size limit, consider storing the file manually within a single
document. You may use the BinData data type to store the binary data.
See your drivers documentation for details on using BinData.

数据库主从同步

原理图

NoSQL 5

达到图是MongoDB采用Replica Sets模式之联手流程

  • 红箭头表示写操作写及Primary上,然后异步同步到差不多独Secondary上
  • 蓝色箭头表示读操作可以从Primary或Secondary任意一个臻读
  • 各个Primary与Secondary之间一直保持心跳同步检测,用于判断Replica
    Sets的状态

数码分片机制

NoSQL 6

  • MongoDB的分片是指定一个分片key来进行,数据据限定分成不同之chunk,每个chunk的大小有限量
  • 发差不多个分片节点保存这些chunk,每个节点保存有的chunk
  • 各个一个分片节点都是一个Replica Sets,这样保证数据的安全性
  • 当一个chunk超过该范围的太老体积时,会分裂成稀独小之chunk
  • 当chunk以分片节点受到遍布不平衡时,会抓住chunk迁移操作

分片时服务器角色

NoSQL 7

上面说了分片的规范,下面是现实性于分片时之几乎栽节点角色

  • 客户端访问行程由于节点mongos来进行多少读写
  • config服务器保存了有限独照关系,一个凡key值的区间对承诺哪一个chunk的照耀关系,另一个凡是chunk存在哪一个分片节点的照关系
  • 总长由于节点通过config服务器获取数据信息,通过这些信息,找到真正存放数据的分片节点进行相应操作
  • 路由于节点还会见在描写操作时判断时chunk是否高于限定大小,如果盖,就分列成稀个chunk
  • 对仍分片key进行的询问及update操作来说,路由于节点会翻动及具体的chunk然后再进行相关的工作
  • 于无循分片key进行的询问以及update操作来说,mongos会对有下属节点发送请求然后再次指向回到结果进行联合

另有关mongodb 的有的有些提示:

  • 永不采用32个本

MongoDB的32位本也是勿建议给应用的,因为你只能处理2GB大小的数。还记首先个限制么?这是MongoDB关于该限量的说明。

  • 叩问官方的限定

被自身倍感愕然的凡,很少有人会询问有关他们即将以的工具的限制。幸好,MongoDB的开发人员发布了千篇一律首MongoDB所有限制的博客,你可提前打探相关消息,避免在用过程中难堪。

  • 主从复制不见面管高可用性

尽管既休建议给使用了,不过MongoDB还是提供了另外一种复制策略,即主从复制。它解决了12单节点限制问题,不过却来了新的题目:如果急需改集群的主节点,那么您必须得手工完成,感到奇怪?看看这链接吧。

  • 透过复制集实现的数目复制效果十分强,不过呢发出限量

MongoDB中数据复制的复制集策略十分深,很容易配置并且用起来实在是。但一旦集群的节点有12个以上,那么你虽见面逢题目。MongoDB中之复制集来12只节点的限量,这里是题材之描述,你可以追踪这个题目看看是不是已经给解决了。

结论

        Gridfs最可那个文件存储
,特别是视频,音频,大型图片超过16MB大小的文本。小型文件为可储存,不过用交2次查询代价(metadata与file
content) [Tip#18 50 Tips and Tricks for MongoDB
Developers]。不要涂改存储文件之情节,而是更新文件首先数据如果版本,或达传新版本的公文,删除老版本的文件。对于大量文件存储时,需要差不多独数据节点,复制,数据分片等。别基于nginx访问图片文件,浏览器没有缓存。
从互联网存储图片案例来拘禁,图片大都是jpg,
png与缩略图文件,分存式文件系统(DFS)会是再次好的化解方案。

资源:

GridFS官方 
Building MongoDB Applications with Binary Files Using
GridFS

网站地图xml地图