3 过程分析与测试
3.1 GridFS概述
由于MongoDB中的Bson对象大小是有限制的,在1.7版本以前单个Bson对象最大容量为4M,1.7版本以后单个Bson对象最大容量为16M[5]。对于一般的文件存储,单个对象的4到16M的存储容量能够满足需求,但无法满足对于一些大文件的存储,如高清图片、设计图纸、视频等,因此在海量数据存储方面,MongoDB提供了内置的Grid
FS,可以将一个大文件分割成为多个较小的文档,可以指定文件分块标准,对用户是透明的。GridFS使用两个数据结构来存储数据:files(包含元数据对象)、chunks(包含其他一些相关信息的二进制块)。为了使多个GridFS命名为一个单一的数据库,文件和块都有一个前缀,默认前缀为fs,用户有权改变这个前缀。
GridFS对Java、C#、Perl、PHP、Python、Ruby等程序言语均支持,且提供了良好的API接口。
3.2 基于GridFS的海量数据存储测试
本文主要采用MongoDB最新版2.0及官方提供的C#语言驱动进行测试,C#驱动下载地址:https://github.com/mongodb/Mongo-csharp-driver。
MongoDB在bin目录下提供了一系列有用的工具,可以很方便的进行运维管理:
(1)bsondump:将Bson格式的文件转储为Json格式的数据。
(2)mongo:客户端命令行工具,支持js语法。
(3)mongod:数据库服务端,每个实例启动一个进程,可以fork为后台运行。
(4)mongodump:数据库备份工具。
(5)mongorestore:数据库恢复工具。
(6)mongoexport:数据导出工具。
(7)mongoimport:数据导入工具。
(8)mongofiles:GridFS管理工具,可实现二进制文件的存取。
(9)mongos:分片路由,如果使用了sharding功能,则应用程序连接的是mongos,而非mongod。
(10)mongosniff:这一工具的作用类似于tcpdump,不同的是他只监控MongoDB相关包请求,并且是以指定的可读性的形式输出。
(11)mongostat:实时性能监控工具。
同时有好几个第三方提供的客户端图形工具,如MongoVUE、RockMongo、MongoHub等,方便管理和维护。
GridFS结合自动分片及自动复制技术,可以实现高性能的分布式数据库集群架构,从而进行海量数据存储,如下图2所示。
图2 高性能的分布式数据库集群架构
MongoDB Sharding Cluster需要三种角色:
(1)Shard Server:即存储实际数据的分片,每个Shard可以是一个mongod实例,也可以是一组mongod实例构成的Replica Set。
(2)Config Server:用来存储所有shard节点的配置信息、每个chunk的shard key范围、chunk在各shard的分布情况、该集群中所有DB和collection的sharding配置信息。
(3)Route Process:这是一个前端路由,客户端由此接入,然后询问Config Servers需要到哪个shard上查询或保存记录,再连接相应的shard进行操作,最后将结果返回给客户端,而这一切对客户端是透明的,客户端不用关心所操作的记录存储在哪个shard上。
为了测试方便,下面在同一台物理机器上构建一个简单的Sharding Cluster,如下图3所示。
图3 简单的Sharding Cluster架构图
配置测试环境如下:
模拟2个Shard服务器和1个Config服务器,均运行在本机127.0.0.1上,只是端口不同:
(1)Shard Server1:127.0.0.1:27020。
(2)Shard Server2:127.0.0.1:27021。
(3)Config Server:127.0.0.1:27022。
(4)Route Process:127.0.0.1:27017。
启动相关服务进程:
c:\mongodb 2.0.0\bin>mongod --shardsvr --dbpath "c:\mongodb 2.0.0\db" --port 27020
d:\mongodb 2.0.0\bin>mongod --shardsvr --dbpath "d:\mongodb 2.0.0\db" --port 27021
e:\mongodb 2.0.0\bin>mongod --configsvr --dbpath "e:\mongodb 2.0.0\db" --port 27022
e:\mongodb 2.0.0\bin>mongos --configdb 127.0.0.1:27022
配置Sharding:
(1)e:\mongodb 2.0.0\bin>mongo
(2)use admin
(3)db.runCommand( { addshard : "127.0.0.1:27020", allowLocal : 1,
maxSize:2 , minKey:1, maxKey:10 } )
(4)db.runCommand( { addshard : "127.0.0.1:27021", allowLocal : 1, minKey:100 } )
(5)config =connect("127.0.0.1:27022")
(6)config = config.getSisterDB("config")
(7)ecDocs=db.getSisterDB("ecDocs")
(8)db.runCommand({enablesharding:"ecDocs"})
(9)db.runCommand( { shardcollection : "ecDocs.filedocs.chunks", key : { files_id : 1 } } )
(10)db.runCommand( { shardcollection : "ecDocs.filedocs.files", key : { _id : 1 } } )
以上的ecDocs是指数据库名,filedocs是指用户自定义的GridFS的文件集合名,系统默认文件集合名为fs。
使用官方提供的C#驱动,需要在程序中引用MongoDB.Driver.dllMongoDB.Bson.dll,循环添加同一文件到GridFS示例代码,如下图4所示。
图4 循环添加同一文件到GridFS代码
测试配置环境如下:
操作系统:WindowsXP专业版32位SP3。
处理器(CPU):英特尔Xeon(至强)W3503@2.40GHz。
内存:3567MB(DDR31333MHz/FLASH)。
硬盘:希捷ST3250318AS(250GB/7200转/分)。
由于本机是32位操作系统,因此单个服务实例只支持GridFS的文件容量大小为0.9G左右,由于采用了两台Shard服务实例,可以支持存储的文件总容量大小为1.8G左右,如果是64位操作系统就没有此限制。
本文主要测试GridFS采用循环插入大容量文件的性能和分片容量大小,测试结果,如下图5所示。
从图5可以看出,第1到3步骤,只添加单个文件时,Shard2并没有产生分片数据,只有测试到步骤4连续添加100个相同文件时Shard2才产生分片数据,并且添加三四百兆的单个文件,只需11秒多就完成了操作,而即使通过文件拷贝方式这么大的文件也至少需要二三十秒才能完成,可见MongoDB在大容量文件存储方面拥有非常高的性能。
通过在客户端的mongo工具输入db.printShardingStatus()命令可以查看详细分片情况,如下图6所示。
从图6可以看出,在shard1中分配了6个chunks,在shard2中分配了7个chunks,分片数据相对还是比较均匀的。
从以上的测试可以得知,采用GridFS可以存储海量数据,并且可以通过廉价服务器进行大规模数据库集群,非常容易扩展部署,程序编码也非常容易,因此能够有效支持云存储的应用,能够满足大规模数据存储的应用需求。
图5 GridFS大容量文件测试结果
图6 GridFS大容量文件分片信息
4 结论
随着企业和个人数据的不断扩大,随着云计算的高速发展,越来越多的应用需要存储海量数据,并且对高并发和处理海量数据提出了更高的要求,传统的关系型数据库对于这些应用场景难以满足应用需求,而作为NoSQL数据库之一的MongoDB数据库能够完全满足和解决在海量数据存储方面的应用,越来越多的大网站和企业选择MongoDB代替Mysql进行存储。