06 June 2014

作者

刘文学

版本

0.1 : 初始化

1)本文档仅从宏观阐述 MongDB 的各方面指标,并不设计具体细节,作为存储系统选择的参考 2)主要以 MongoDB 2.6 为参考

简介

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散的 bjson(类似 json) 格式,因此可以存储比较复杂的数据类型。MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它是一个面向集合的,模式自由的文档型数据库。

特点

  • 文档数据模型(Document Data Model)
  • 丰富的搜寻模型(Rich Query Model)
  • 符合习惯的驱动(Idiomatic Driver)
  • 横向扩展(Horizontal Scalability)
  • 高可用(High Availability)
  • 内存性能(In-Memory Performance)
  • 灵活性(Flexibility)

安装

RHE和 Debian支持 包管理器安装,其他 linux 源码安装

支持 windows 和 OS X

数据模型

数据即文档

数据即文档的BSON存储格式。

数据模型数据模型

上图展示了关系型数据库和 MongoDB在数据模型上的区别

  • Database 可以有多个数据库,每个数据库作为一个相互独立的容器。每个数据库可以包含一个或多个集合(collection).

  • Colleciton 存储一组相互关联的 Document,这些 Document 都有共同的索引 id。 在逻辑上相当于关系型数据库中的表。但是与表不同的是,在存储数据时可以动态地增加数据结构,即动态模式。

  • Document 存储文档的单位。BSON格式(二进制的Json的格式)的一系列字段或键值对({field:value})。field 是字符串,value 可以是各种类型:字符串,整数,浮点数,时间戳,布尔值等等,甚至可以存储另一个文档。类似于关系型数据库的 record。

两种方式:

  • 内嵌(Embed) 一对一 一对多

  • 连接(Link) 多对多

参考附录获取有关动态模式和 BSON 的信息

架构

架构

这是一个典型的应用分片复制集的架构。

自动分片(aut-sharding)机制

为了增加数据读写速度,满足大数据和分布式的需求,利用分片机制 实现横向扩展。 mongodb通过 mongos 自动建立一个水平扩展的数据库集群系统,将集合切合成小块,分散到若干片里面,每个片负责所有数据的一部分。这些块对应用程序来说是透明的,不需要知道哪些数据分布到哪些片上,甚至不在乎是否有做过分片,应用程序连接mongos进程,mongos 知道数据和片的对应关系,将客户端请求转发到正确的片上,如果请求有了响应,mongos将结果收集起来返回给客户端程序。

分片适用场景

  • 服务器磁盘不够用
  • 单个mongod不能满足日益频繁写请求
  • 将大量数据存放于内存中提高性能

组成

  • Shard Server 用于存储实际的数据块,每个shard可以是单个的mongod实例,也可以是Replica Set,即使片内又多台服务器,只能有一个主服务器,其他的保存相同数据的副本。为了实现每个shard内部的 auto-failover,强烈建议为每个shard配置一组Replica Set,确保每个数据节点都具有备份、自动容错转移、自动恢复能力。

  • Config Server 为了将一个特定的collection 存储在多个shard 中,需要为该collection 指定一个shardkey,shardkey 可以决定该条记录属于哪个chunk。Config Servers 就是用来存储:所有shard 节点的配置信息、每个chunk 的shardkey 范围、chunk 在各shard 的分布情况、该集群中所有DB 和collection 的sharding 配置信息。

  • Route Server mongos 实例,配合 LVS,实现负载平衡,提高接入性能(high performance)。集群前端路由,路由所有请求,然后将结果聚合,且让整个集群看上去像单一数据库,前端应用可以透明使用。当客户端由此接入,询问config server需要到哪些 shard 上查询或保存数据,再连接到相应的 shard 进行操作,最后将结果返回给客户端。客户端只需要将原先发送给 mongod 的请求原封不动的发给 mongos 即可,不必数据分布在哪个shard上。

  • shard key 设置分片时,需要从集合中选一个键,作为数据拆分的依据,这个键就是shard key。shard key的选择决定了插入操作在片之间的分布。 shard key保证足够的不一致性,数据才能更好的分布到多台服务器上。同时保持块在一个合理的规模是非常重要的,这样数据平衡和移动块不会消耗大量的资源。

三种形式的 Sharding

  • 基于 Range 的 Sharding : 为优化范围查找而设计
  • 基于 Hash 的 Sharding : 为了写的分布式
  • 标签感知(Tag-aware)的 sharding :优化文档定位

复制集(repica set)机制

为了实现高可用,Replica Set使用的是n个mongod节点,构建具备自动的容错功能(auto-failover),自动恢复的(auto-recovery)的高可用方案。

MongoDB的复制集至少需要两个实例。其中一个是主节点(primary replica),负责处理客户端请求,其余的都是从节点(secondary replica),负责复制主节点上的数据。

主节点利用 oplog 备份数据到从节点:

  • 当从节点宕机后,有同步进程自动备份数据。
  • 当主节点宕机后,利用 election 机制来决定哪个从节点自动变为主节点,当 primary 恢复后,自动变为从节点。

日志(journal)机制

用于写操作,当一个写请求发生,首先会更改 private view (cache)中的数据,然后默认每 100 毫秒刷新到journal log。journal log 有一个记录当前日志点的 pointer。然后应用journal log 中的写操作到 share view ,这时share view 就和数据文件不一致。然后默认每隔 60 秒,mongodb会请求操作系统刷新 shared view 中更改的数据到数据文件。然后 mongdb 会把 journal log 中记录更改数据日志点的 pointer,以前的数据删除掉。为了数据的一致性,Mongodb 通常会请求操作系统重新把 share view 指向 private view。

更详细日志机制参考这里

存储机制

读操作

对于读写,一般的数据流都是Driver 或 Application 发起请求(写或读),在 router 处,根据 shard key 查找存储元数据 Config Server, 如果找到匹配的 Shard,就直接访问对应的 Shard。 如果没有,则访问所有的 Shard。

  • 写后直接返回

读 shard 操作

  • 确认写成功后返回

读 shard 操作

  • 确认写成功后,并且写入日志(journal)后返回

读 shard 操作

  • 以上默认只要写入 primary 节点,为了更加安全,可以配置同时写入 secondary 成功后才返回

读 shard 操作

当单对象大于 16M, 需要用 GridFS 来存储。

  • 如果有 shard key,首先查找的 shard key 到 config Server 元数据库中找到匹配的 Shard,之后从对应的 Shard 读取需要的 document,见下图

读 shard 操作

  • 如果没有没有给出 shard key 时会遍历全部的 Shard。见下图

读 shard 操作

  • 默认都从 Shard 的 primary 节点读,当然通过配置可以从 Shard 的 secondary 读。见下图

读 replica 操作读 shard 操作

查询:

  • 映射(projection) :限制输出
  • 准则(criteria) : 限制 filed
  • 条件(conditions):限制条件
  • 游标(Cursors): 类似迭代器

原理

内存管理

mongodb使用内存映射文件进行数据管理。把所有空闲内存当缓存使用,而且不能指定内存大小。

  • 对于内存:Mongodb及其消耗内存,有多少吃多少。
  • 内存充足:Mongodb在内存充足时,将全部的索引(hash)与数据存放在内存中,同时将所有数据压缩后映射到磁盘。
  • 内存不够:Mongodb在内存不够时,将全部的索引(hash)与部分热数据存放内存中,同时将所有数据压缩后映射到磁盘

持久化

利用日志来支持持久化

默认情况下 mongodb 每 100 毫秒往 journal 文件中 flush 一次数据,不过这是在数据文件和 journal 文件处于同一磁盘卷上的情况,而如果数据文件和 journal 文件不在同一磁盘卷上时,默认刷新输出时间是30毫秒。不过这个毫秒值是可以修改的,可修改范围是 2~300,值越低,刷新输出频率越高,数据安全度也就越高,但磁盘性能上的开销也更高。

journal 文件是以“j._”开头命名的,且是 append only 的,如果1个 journal 文件满了1G大小,mongodb 就会新创建一个 journal 文件来使用,一旦某个 journal文件所记载的写操作都被使用过了,mongodb 就会把这个 journal 文件删除。通常在 journal 文件所在的文件夹下,只会存在2~3个 journal 文件,除非你使用 mongodb 每秒都写入大量的数据。而使用 smallfiles 这个运行时选项可以 将 journal 文件大小减至 128M 大小。

备份和恢复

支持完全自愈(fully self-healing)分片的主从模式来备份数据,防止宕机造成数据的丢失。由于是完全自动化的,减少了运维的难度。可用mongodump命令来备份MongoDB数据

备份方式

  • 文件快照方式
  • 复制数据文件方式
  • 使用mongodump方式

当宕机后,利用日志来恢复丢失文档。mongorerstore 命令来恢复备份的数据,

原地更新(In-Place Update)

每个 Document 在硬盘上都存储为连续的块。分配空间给document,在原地(in-place)更新。 这样可以支持离散(discrete)、区域水平(field-level)的更新,极少了磁盘IO,只更新需要 更新的索引点(index entries)。较运行时压缩的方式能够更加有效利用磁盘空间。

工具集

命令行

* mongostat – 实时性能监控工具 * mongoexport/mongoimport – 数据导出和导入工具

  • mongofiles –  GridFS管理工具,可实现二制文件的存取
  • mongos – 分片路由,如果使用了sharding功能,则应用程序连接的是mongos而不是 mongod
  • mongosniff – 这一工具的作用类似于tcpdump,不同的是他只监控MongoDB相关的包请求,并且是以指定的可读性的形式输出
  • bsondump – 将bson格式的文件转储为json格式的数据
  • mongo – 客户端命令行工具,其实也是一个js解释器,支持js语法
  • mongod – 数据库服务端,每个实例启动一个进程,可以fork为后台运行
  • mongodump/mongorestore – 数据库备份和恢复工具

GUI

  • Fang of Mongo – 网页式,由Django和jQuery所构成
  • MongoVUE :GUI 管理工具
  • RockMongo : 最好的PHP语言的MongoDB管理工具,轻量级, 支持多国语言.
  • MongoHub : 适用于OSX的管理工具。
  • Opricot : 一个基于浏览器的MongoDB控制台, 由PHP撰写而成
  • Database Master — Windows的mongodb管理工具

  • 支持 Map/Reduce 工具

插件式

MongoDB提供了网络和系统监控工具Munin,它作为一个插件应用于MongoDB。

Gangila是MongoDB高性能的系统监视的工具,它作为一个插件应用于MongoDB。

基于图形界面的开源工具 Cacti, 用于查看CPU负载, 网络带宽利用率,它也提供了一个应用于监控 MongoDB 的插件。

适用场景

  • 持久化缓存层
  • 实时数据存储
  • BSON数据格式非常适合文档化格式的存储和查询
  • 数十台或上百台的数据库集群

不适用场景

  • 高度事务性系统
  • 商业智能应用
  • 复杂的跨表级联查询

案例

  • Craiglist上使用MongoDB的存档数十亿条记录。
  • FourSquare,基于位置的社交网站,在Amazon EC2的服务器上使用MongoDB分享数据。
  • Shutterfly,以互联网为基础的社会和个人出版服务,使用MongoDB的各种持久性数据存储的要求。
  • bit.ly, 一个基于Web的网址缩短服务,使用MongoDB的存储自己的数据。
  • spike.com,一个MTV网络的联营公司, spike.com使用MongoDB的。
  • Intuit公司,一个为小企业和个人的软件和服务提供商,为小型企业使用MongoDB的跟踪用户的数据。
  • sourceforge.net,资源网站查找,创建和发布开源软件免费,使用MongoDB的后端存储。
  • etsy.com ,一个购买和出售手工制作物品网站,使用MongoDB。
  • 纽约时报,领先的在线新闻门户网站之一,使用MongoDB。
  • CERN,著名的粒子物理研究所,欧洲核子研究中心大型强子对撞机的数据使用MongoDB。

附录

ACID 的支持

  • document 层次支持 ACID。
  • 利用轻量级的锁来支持高并发访问。并发控制类似 Latch 的概念(多读单写)
  • 一致性支持强一致性和最终一致性

动态模式

document 是自描述的,不需要向系统声明 document 的结构,此外,document 可以动态增加 filed,不需要更新中心分类系统,也不需要离线。

BSON

BSON是MongoDB默认的数据交换格式。与XML和JSON相比BSON的优势在于内存的消耗和处理时间上更高效。JSON支持BSON支持的所有数据类型,同时还支持一些特殊的数据类型,比如正则表达式,对象ID,日期,二进制数据和代码。更好的移植性,编程语言如PHP,PYTHON,JAVA等等可以直接从BSON格式进行转换,易于与MongoDB融合和管理维护数据。 [1]: /assets/img/mongdb/MongDB-APP.png