MongoDB原理及功能特性

一、mongodb

1、简介

1)mongodb是一款强大,灵活,易于扩展的通用数据库。
2)MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,可以添加更多的节点,来保证服务器性能。
3)MongoDB 将数据存储为一个文档,数据结构由键值对组成。
4)MongoDB 文档使用BSON格式;字段值可以包含其他文档,数组及文档数组。
5)Mongodb的强大在于性能强;灵活在于数据存储为文档型,具有nosql的特性,没有复杂的表结构的约束;易于扩展在于mongodb原生的这种副本集,分库分表的架构非常易于管理。

6)MongoDB以BSON做为其存储结构的一种重要原因是其可遍历性。
7)BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON,它和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。
  BSON可以做为网络数据交换的一种存储形式,这个有点类似于Google的Protocol Buffer,但是BSON是一种schema-less的存储形式,它的优点是灵活性高,但它的缺点是空间利用率不是很理想。
  BSON有三个特点:轻量性、可遍历性、高效性。
  MongoDB使用了BSON这种结构来存储数据和网络数据交换。把这种格式转化成一文档这个概念,因为BSON是schema-free的,所以在MongoDB中所对应的文档也有这个特征,这里的一个文档也可以理解成关系数据库中的一条记录,只是这里的文档的变化更丰富一些,如文档可以嵌套。作为nosql型数据库,易于使用的的特点显而易见。文档模型不再有“row”的概念,通过在文档中期嵌入文档和数组,通过使用一条记录就可以表现复杂的层次关系。

2、易于扩展的架构

Mongodb采用横向扩展。面向文档型的数据模型可以让他很容易在多台机器之间进行数据拆分,通过制定唯一的key作为片键。Mongodb采用mongos+mongo-route+shard的架构,能够自动处理夸集群的数据分布,自动均衡数据,和将请求路由到正确的节点上。对于开发者,只需要集中精力编写应用程序,而不需要考虑如何扩展数据的问题。原生的分片机制给DBA减轻了大量的工作负担。

3、功能

Mongodb作为一款通用型数据库,除了最基本的增删改查功能,还提供了一些不断扩展的独特的功能。
* 索引 indexing
mongodb支持通用二级索引,唯一索引,复合索引,地理空间索引,过期索引和全文索引。对比mysql的innodb引擎,索引的功能更加丰富。
* 聚合 aggregation
MongoDB支持“聚合管道”(aggregation pipeline)。这部分内容对研发更优化,DBA可以简单理解
* 特殊的集合类型
Mongodb支持时间有限的集合,也就是实现了数据自动过期的功能,对于一些要指定清理的数据,如log,登录流水,操作记录等等,再合适不过了。
* 文件存储 file storage
Mongodb对文件存储,采用了更简单易用的协议,用于存储大文件和文件的元数据。(可以再深入找一下资料)

Mongodb对比SQL数据库,也有不惧备的功能,比如连接(join)以及多行事务–大事务。省略这些功能是出于架构的考虑,易于扩展。(表连接于架构扩展冲突),在分布式系统中,这个功能难以高效实现。

4、关键特点

1)高性能
2)丰富的查询语言
4)副本集,自动故障转移,数据冗余
3)高可用性
5)水平可扩展性
6)支持多种存储引擎

MMAPv1存储引擎:< 3.2的默认存储引擎
WirdeTiger存储引擎:>=3.2的默认存储引擎
In-Memory存储引擎:Changed in version 3.2.6

5、默认库

MongoDB有三个默认库:admin、local、config。

admin:
从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
local:
这个库的数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合。
config:
当MongoDB用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
7、存储引擎

1) WirdeTiger 基本介绍

3.2之后的默认存储引擎,用于将数据持久化存储到硬盘文件中,WiredTiger提供文档级别的并发控制,检查点,数据压缩和本地数据加密等功能。对于生产环境,更多的CPU可以有效提升wireTiger的性能,因为它是多线程的。wiredTiger不像MMAPV1引擎那样尽可能的耗尽内存,它可以通过在配置文件中指定“cacheSizeGB”参数设定引擎使用的内存量,此内存用于缓存工作集数据(索引、namespace,未提交的write,query缓冲等)。

2)文档级别的并发控制

MongoDB在执行写操作时,WiredTiger 在文档级别进行并发控制,就是说,在同一时间,多个写操作能够修改同一个集合中的不同文档;当多个写操作修改同一个文档时,必须以序列化方式执行;这意味着,如果该文档正在被修改,其他写操作必须等待,直到在该文档上的写操作完成之后,其他写操作相互竞争,获胜的写操作在该文档上执行修改操作。
  对于大多数读写操作,WiredTiger使用乐观并发控制,只在Global,database和Collection级别上使用意向锁,如果WiredTiger检测到两个操作发生冲突时,导致MongoDB将其中一个操作重新执行,这个过程是系统自动完成的。

3)检查点

在检查点操作开始时,WiredTiger提供指定时间点的数据库快照,该快照呈现的是内存中数据的一致性视图。当向磁盘写入数据时,WiredTiger将快照中的所有数据以一致性方式写入到数据文件中。一旦检查点创建成功,WiredTiger保证数据文件和内存数据是一致性的,因此,检查点担当的是还原点,检查点操作能够缩短MongoDB从Journal日志文件还原数据的时间。
  当WiredTiger创建检查点时,MongoDB将数据刷新到数据文件中,在默认情况下,WiredTiger创建检查点的时间间隔是60s,或产生2GB的Journal文件。在WiredTiger创建新的检查点期间,上一个检查点仍然是有效的,这意味着,即使MongoDB在创建新的检查点期间遭遇到错误而异常终止运行,只要重启,MongoDB就能从上一个有效的检查点开始还原数据。
  当MongoDB以原子方式更新WiredTiger的元数据表,使其引用新的检查点时,表明新的检查点创建成功,MongoDB将老的检查点占用的磁盘空间释放。使用WiredTiger 存储引擎,如果没有记录数据更新的日志,MongoDB只能还原到上一个检查点;如果要还原在上一个检查点之后执行的修改操作,必须使用Jounal日志文件。

4) 预写记录日志

WiredTiger使用预写日志的机制,在数据更新时,先将数据更新写入到日志文件,然后在创建检查点操作开始时,将日志文件中记录的操作,刷新到数据文件,就是说,通过预写日志和检查点,将数据更新持久化到数据文件中,实现数据的一致性。WiredTiger 日志文件会持久化记录从上一次检查点操作之后发生的所有数据更新,在MongoDB系统崩溃时,通过日志文件能够还原从上次检查点操作之后发生的数据更新。

5) 内存使用

WiredTiger 利用系统内存资源缓存两部分数据:

内部缓存(Internal Cache)
文件系统缓存(Filesystem Cache)

从MongoDB3.2版本开始,WiredTiger内部缓存的使用量,默认值是:1GB 或 60% of RAM - 1GB,取两值中的较大值;文件系统缓存的使用量不固定,MongoDB自动使用系统空闲的内存,这些内存不被WiredTiger缓存和其他进程使用,数据在文件系统缓存中是压缩存储的。
  WiredTiger压缩存储集合和索引,压缩减少磁盘空间消耗,但是消耗额外的CPU执行数据压缩和解压缩的操作。
  默认情况下,WiredTiger使用块压缩算法来压缩Collections,使用前缀压缩算法来压缩Indexes,Journal日志文件也是压缩存储的。对于大多数工作负载,默认的压缩设置能够均衡数据存储的效率和处理数据的需求,即压缩和解压的处理速度是非常高的。
  当从MongoDB中删除文档或集合后,MongoDB不会将磁盘空间释放给OS,MongoDB在数据文件中维护Empty Records的列表。当重新插入数据后,MongoDB从Empty Records列表中分配存储空间给新的文档,因此,不需要重新开辟空间。为了更新有效的重用磁盘空间,必须重新整理数据碎片。
  WiredTiger使用compact 命令,移除集合中数据和索引的碎片,并将unused的空间释放,调用语法:

db.runCommand ( { compact: '<collection>' } )

在执行compact命令时,MongoDB会对当前的database加锁,阻塞其他操作。在compact命令执行完成之后,mongod会重建集合的所有索引。

8、mongoDB日志

数据是MongoDB的核心,MongoDB必须保证数据的安全,不能丢失,Journal 是顺序写入的日志文件,用于记录上一个检查点之后发生的数据更新,能够将数据库从系统异常终止事件中还原到一个有效的状态。MongoDB使用预写日志机制实现数据的持久化:WiredTiger 存储引擎在执行写操作时,先将数据更新写入到Journal文件。Journal Files是存储在硬盘的日志文件,每个Journal File大约是100MB,存储在–dbpath下的Journal子目录中,在执行检查点操作,将数据的更新同步到数据文件。
  每隔一定的时间间隔,WiredTiger 存储引擎都会执行检查点操作,将缓存的数据更新日志同步到硬盘上的数据文件中(On-磁盘 Files),在默认情况下,MongoDB启用日志记录,也可以显式启用,只需要在启动mongod 时使用–journal 参数:

mongod --journal

1)使用Journal日志文件还原的过程

WiredTiger创建检查点,能够将MongoDB数据库还原到上一个CheckPoint创建时的一致性状态,如果MongoDB在上一个检查点之后异常终止,必须使用Journal日志文件,重做从上一个检查点之后发生的数据更新操作,将数据还原到Journal记录的一致性状态,使用Journal日志还原的过程是:

获取上一个检查点创建的标识值:从数据文件(Data Files)中查找上一个检查点发生的标识值(Identifier);
根据标识值匹配日志记录:从Journal Files 中搜索日志记录(Record),查找匹配上一个检查点的标识值的日志记录;
重做日志记录:重做从上一个检查点之后,记录在Journal Files中的所有日志记录;

2)缓存日志

MongoDB配置WiredTiger使用内存缓冲区来存储Journal Records,所有没有达到128KB的Journal Records都会被缓存在缓冲区中,直到大小超过128KB。在执行写操作时,WiredTiger将Journal Records存储在缓冲区中,如果MongoDB异常关机,存储在内存中的Journal Records将丢失,这意味着,WiredTiger将丢失最大128KB的数据更新。

3)日志文件

关于Journal文件,MongoDB在 --dbpath 目录下创建 journal子目录,WiredTiger将Journal 文件存储在该目录下,每一个Journal文件大约是100M,命名格式是:WiredTigerLog.,sequence是一个左边填充0的10位数字,从0000000001开始,依次递增。
  对于WiredTiger存储引擎,Journal 文件具有以下特性:

标识日志记录:Journal文件的每一个日志记录(Record)代表一个写操作;每一个记录都有一个ID,用于唯一标识该记录; 压缩Journal文件:WiredTiger会压缩存储在Journal文件中的数据; Journal文件大小的上限:每一个Journal文件大小的上限大约是100MB,一旦文件超过该限制,WiredTiger创建一个新的Journal文件; 自动移除Journal文件:WiredTiger自动移除老的Journal文件,只维护从上一个检查点还原时必需的Journal文件; 预先分配Journal文件:WiredTiger预先分配Journal文件;

4)在异常宕机后恢复数据

在MongoDB实例异常宕机后,重启mongod实例,MongoDB自动重做(redo)所有的Journal Files,在还原Journal Files期间,MongoDB数据库是无法访问的。

9、副本集相关

1) 副本集概念

MongoDB副本集是由一个主节点和多个副本节点组成。主节点将数据的改变推送到副本节点上,在一定的延迟之后,每个MongoDB实例维护相同的数据。通过维护冗余的数据副本,能够实现数据的备份,读写分离和自动故障转移。

2) 副本集使用场景

  • 数据冗余,用做故障恢复使用,当发生硬件故障或者其它原因造成的宕机时,可以使用副本进行恢复。
  • 读写分离,读请求会分流到所有副本上,减轻主节点的读压力。

3) 副本集的故障转移

MongoDB副本集是主从复制的高级形式。主从复制仅仅实现了数据备份和读写分离,但是主节点一旦宕机,需要手动启动从节点进行故障转移;MongoDB副本集在主从复制基础上实现了故障转移的功能,也就是当主节点宕机时,某一台副本节点会自动提升为新主节点。

4)复制集成员最多50个。参与Primary选举投票的成员最多7个,其他成员的votes属性必须设置为0,即不参与投票。一般而言,副本集节点有3中类型,主节点(Primary)、副本节点(Secondary)、仲裁节点(Arbiter)。

5) 主节点

和其他数据库上的主节点一样,可以提供读写服务。

6)副本节点

副本节点也基本上和其他类型数据库的从节点一样,可以实现备份和读写分离的作用。MongoDB的副本节点可以设置以下几个属性:

7)优先级为0的节点

优先级为0的节点的特点:

  • 不会升级为主节点;但是可以投票。
  • 此节点正常参与主节点产生的oplog的读取,进行数据备份和命令执行。
  • 此节点可正常参与客户端对于数据的读取,进行担当负载均衡的工作。

Priority=0在mongoDB中的解释就是一个Standby,可投票不可参选,并且承担负载。对于Priority为0节点的情况,通常作为一个standby,或由于硬件配置较差,设置为0以使用不可能成为主。

8)隐藏节点

这个隐藏节点是对客户端的隐藏,客户端如果要读取副本节点的数据,永远无法读取隐藏节点的数据,因为设置了隐藏的这个节点对于客户端是透明的,不可见。但是,对于副本节点和主节点来说都是可见的,所以,隐藏节点依然可以投票,依然要按照oplog进行命令的复制,只是不参与负载了。
Hidden属性的前提是必须是一个Priority=0的节点,所以会具备一些优先级=0的特点。

  • 隐藏节点不能被选为主(Priority为0),并且对Driver不可见。
  • 在隐藏节点上,可做一些数据备份、离线计算的任务,不会影响复制集的服务。
  • 隐藏节点成员建议总是将其优先级设置为0。
  • 由于对Driver不可见,因此不会作为读节点,隐藏节点可以作为投票节点。
  • 在分片集群当中,mongos不会同隐藏节点交互。
10、事务相关

MongoDB从 3.0版本引入WiredTiger存储引擎之后开始支持事务,MongoDB 3.6之前的版本只能支持单文档的事务,从MongoDB 4.0版本开始支持复制集部署模式下的事务,从MongoDB 4.2版本开始支持分片集群中的事务。

1)与关系型数据库一样,MongoDB事务同样具有ACID特性,说明如下。

  • 原子性(Automicity):一个事务要么完全执行成功,要么不做任何改变。
  • 一致性(Consistency):当多个事务并行执行时,元素的属性在每个事务中保持一致。
  • 隔离性(Isolation):当多个事务同时执行时,互不影响。WiredTiger本身支持多种不同类型的隔离级别,如读-未提交(read-uncommitted)、读-已提交(read-committed)和快照(snapshot)隔离。MongoDB默认选择的是快照隔离。
  • 持久性(Durability):一旦提交事务,数据的更改就不会丢失。

2)事务的snapshot隔离

WiredTiger存储引擎支持read-uncommitted、read-committed和snapshot3种事务隔离级别,MongoDB启动时默认选择snapshot隔离。
事务开始时,系统会创建一个快照,从已提交的事务中获取行版本数据,如果行版本数据标识的事务尚未提交,则从更早的事务中获取已提交的行版本数据作为其事务开始时的值。
通过事务可以看到其他还未提交的事务修改的行版本数据,但不会看到事务id大于snap_max的事务修改的数据。

3)MVCC并发控制机制

要实现事务之间的并发操作,可以使用锁机制或MVCC控制等。对于WiredTiger来说,使用MVCC控制来实现并发操作,相较于其他锁机制的并发,MVCC实现的是一种乐观并发机制。

4)事务日志(Journal)

Journal是一种WAL(Write Ahead Log)事务日志,目的是实现事务提交层面的数据持久化。
Journal持久化的对象不是修改的数据,而是修改的动作,以日志形式先保存到事务日志缓存中,再根据相应的配置按一定的周期,将缓存中的日志数据写入日志文件中。
事务日志落盘的规则如下。

(1)按时间周期落盘。
在默认情况下,以50毫秒为周期,将内存中的事务日志同步到磁盘中的日志文件。
(2)提交写操作时强制同步落盘
当设置写操作的写关注为j:true时,强制将此写操作的事务日志同步到磁盘中的日志文件。
(3)事务日志文件的大小达到100MB

  • 12
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值