Mongodb的文件管理
来源:互联网 发布:php while 死循环 编辑:程序博客网 时间:2024/05/24 04:53
MongoDB数据文件
在MongoDB的数据文件夹中(默认路径是/data/db)由构成数据库的所有文件。每一个数据库都包含一个.ns文件和一些数据文件,其中数据文件会随着数据量的增加而变多。所以如果有一个数据库名字叫做foo,那么构成foo这个数据库的文件就会由foo.ns,foo.0,foo.1,foo.2等等组成。
数据文件每新增一次,大小都会是上一个数据文件的2倍,每个数据文件最大2G。这样的设计有利于防止数据量较小的数据库浪费过多的空间,同时又能保证数据量较大的数据库有相应的空间使用。
MongoDB会使用预分配方式来保证写入性能的稳定(这种方式可以使用–noprealloc关闭)。预分配在后台进行,并且每个预分配的文件都用0进行填充。这会让MongoDB始终保持额外的空间和空余的数据文件,从而避免了数据增长过快而带来的分配磁盘空间引起的阻塞。
名字空间和盘区
每一个数据库都由多个名字空间组成,每一个名字空间存储了相应类型的数据。数据库中的每一个Collection都有各自对应的名字空间,索引文件同样也有名字空间。所有名字空间的元数据都存储在.ns文件中。
名字空间中的数据在磁盘中分为多个区间,这个叫做盘区。
MongoDB GridFS
GridFS是基于mongodb存储引擎是实现的“分布式文件系统”,底层基于mongodb存储机制,和其他本地文件系统相比,它具备大数据存储的多个优点。GridFS适合存储超过16MB的大型文件,不过16M数据在当今互联网时代,已经不足为奇。我们可以使用GridFS构建大规模的“图片服务器”、“文档服务器”、“视频、音频”文件服务器,GridFS对于web应用,可以结合nginx插件“ningx-gridfs”能够简单的实现负载均衡等特性,非常便捷;可以简单认为GridFS是为web应用而生。个人认为,目前架构比较简单的NoSQL文件系统中GridFS是最优秀的。
GridFS并不是将单个文件直接存储为一个document,而是将文件分成多个parts或者说chunks,然后将每个chunk作为作为一个单独的document存储,然后将chunks有序保存。默认情况下,GridFS的chunk大小位255k。GridFS使用2个collections来存储这些文件,一个collection存储文件的chunks(实际文件数据),另一个则存储文件的metadata(用户自定义的属性,filename,content-type等)。
当用户查询GridFS中的文件时,客户端或者driver将会重新按序组装这些chunks。用户可以range查询文件,也可以获取文件的任意部分的信息,比如:跳过(skip)视频或者音频(任何文件)的中间部,实现“range access of single file”。
对于mongodb而言,每个document最大尺寸为16M,如果想存储一条数据(比如一个文件)超过16M,那么只能使用GridFS支持;GridFS可以支持单个文件尺寸达到数G,读取文件时可以分段读取。此外,GridFS可以从Mongodb的高性能、高可用特性中获益,比如我们可以在“replica set”或者“sharding”架构模式下使用GridFS。
GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。
GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中。
GridFS 可以更好的存储大于16M的文件。
GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。
GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。
每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。
三、GridFS内部存储结构简析(JAVA代码示例)
比如我们创建了一个GridFS数据库,可以可以通过mongo shell指令看到:
- > ./mongo --host 127.0.0.1 --port 27017
- > use common-fs
- > show collections;
- fs.chunks
- fs.files
- system.indexes
我们可以看到“common-fs”数据库下有2个collection:“fs.chunks”和“fs.files”;其中前缀“fs”为bucket名称。
1)fs.chunks:存储二进制数据,如上文所述,保存在GridFS中的每个文件都会根据“chunkSize”拆分成多个chunks并依次保存在“fs.chunks”中,每个chunk都持有“files_id”即为“文件id”,“n”为chunk的序列;比如一个文件被拆分成3个chunks,那么“fs.chunks”中将会有3个document,它们持有相同的files_id,“n”分别为0、1、2。
- {
- "_id" : <ObjectId>, //chunk ID,全局唯一
- "files_id" : <ObjectId>, //file collection表的"_id"值
- "n" : <num>, //chunk的序列号,第一个chunk位0。
- "data" : <binary> //二进制数据
- }
- > db.fs.chunks.getIndexes();
- [
- ...
- {
- "v" : 1,
- "unique" : true,
- "key" : {
- "files_id" : 1,
- "n" : 1
- },
- "name" : "files_id_1_n_1",
- "ns" : "common-fs.fs.chunks"
- }
- ]
chunks默认情况下已经对“files_id”和“n”建立了唯一索引。
2)fs.files:存储文件的metadata,GridFS每保存一个文件,都会在此collection中插入一条document,结构如下所示。其中“metadata”字段用于保存用户自定义的K-V数据(比如保存文件的format),其他字段是GridFS内置的,开发者不能修改(除file_name外),每个文档都有一个md5字段,所以开发者不需要自己再去计算md5值。其中filename为开发者指定的“文件名称”。
- {
- "_id" : <ObjectId>, //
- "length" : <num>, //文件的长度
- "chunkSize" : <num>, //chunkSize
- "uploadDate" : <timestamp>, //文件生成的时间戳
- "md5" : <hash>, //HASH值
- "filename" : <string>, //文件名,用户指定
- "contentType" : <string>, //
- "aliases" : <string array>, //别名
- "metadata" : <dataObject>, //用户自定的metadata
- }
- > db.fs.files.getIndexes();
- [
- ...
- {
- "v" : 1,
- "key" : {
- "filename" : 1,
- "uploadDate" : 1
- },
- "name" : "filename_1_uploadDate_1",
- "ns" : "common-fs.fs.files"
- }
- ]
其中“filename”和“updateDate”默认已经建立了组合索引,但不是unique,所以GridFS中filename是可以重复的;建议使用_id来获取文档,比如如果你使用GridFS构建一个图片服务器,可以使用_id的值作为图片的名称。
其中有一个比较重要的参数“chunkSize”,这个值默认为“261120”(即255k),对于web应用此值基本不需要调整;如果你的应用是文件的“上传”、“下载”等,可以考虑将此值扩大,比如64M等。还有一种特例,比如你的文件通常较小,比如只有1M左右,而且通常不会涉及到“range access”,那么可以将每个file的chunkSize设置为文档的大小,这样可以在存储时只有一个chunk。
客户端查询文件时首先会查询“fs.files”获取metadata并获得files_id值(即_id),然后再根据files_id查询“fs.chunks”获取chunks列表(根据n排序),当客户端需要读取某个chunk数据时才会触发实际数据传输。
四、Sharding架构
随着GridFS中文件数量的增加,最终有可能存储空间会达到单机磁盘上限,或者由于Read操作较多单机无法承载压力,此时就需要考虑分布式部署;解决此文件的方案为sharding,即将GridFS的数据分布存储在多个mongod节点中。
sharding基本原理和mongodb一样,此处不再赘言;因为一个GridFS数据库,由“fs.files”和“fs.chunks”两个collections构成,一个文件将不同的信息保存在两个collections中,那么究竟该如何设计sharding呢?首先表明无论两个collection同时sharding还是只有其中一个sharding,都不需要客户端修改代码,也不会影响数据访问,因为无论是“通过filename查询fs.files”还是“通过files_id查询fs.chunks”中间都会经过mongos实例路由。
因为fs.files文件中只保存metadata,通常都比较小,因此在可以不sharding。如果sharding,则根据应用需要选择合适的“shard key”,比如你通常使用_id来查询文件,那么可以将_id作为“shard key”的一部分(比如shard key为{_id : 1,filename:1}),如果你的应用通常使用filename查询文件,那么可以将filename作为shard key(或者前缀);我们最终的目的,就是确保查询方式与数据sharding保持一致,提供高效的查询,同时还需要尽可能保证数据的均匀分布。
对于fs.chunks文件,这个是优先被sharding的,因为它的数据量通常为fs.files的数倍;不过这个collection的shard key只能为{"files_id" : 1, n : 1},因为这个collection只有这种查询方式,且只有这样才会保证同一个file_id的多个chunk尽可能的保存在同一个shard-chunk中。
- Mongodb的文件管理
- MongoDB的管理操作
- 8 MongoDB的管理
- MongoDB的用户管理
- mongoDB 分片的管理
- MongoDB的管理
- mongodb 的用户管理
- mongoDB 分片的管理
- 浅述MongoDB的管理操作
- MongoDB的日常维护管理
- MongoDB的管理与监控
- MongoDB数据库的索引管理
- 用MongoVUE管理MongoDB MongoDB的管理客户端
- mongodb- 管理
- MongoDB 管理
- mongoDB 管理
- mongodb管理
- mongodb管理
- java的jvm和操作系统的关系
- Canvas学习笔记之画线
- C语言---数字迷宫
- 406. Queue Reconstruction by Height | Leecode Greedy
- 【PHP】给两个字符串返回字符串按排序出两个字符串的字符de多种解法
- Mongodb的文件管理
- spring的aop的使用
- 安卓文件存在但是unity中通过www读取失败
- [NOIP2017模拟]电影
- solr-9 InitParams in SolrConfig
- BZOJ 1939 [Croatian2010] Zuma
- 关于 1px
- 在Fragment中使用startActivityForResult和onActivityResult
- Servlet 简要概述