haizdl
作者haizdl·2020-12-15 16:42
技术经理·大连

NOSQL DB:MongoDB 七问

字数 5953阅读 3096评论 0赞 3

1. MongoDB 是什么?

按照官方解释, MongoDB 是一款基于文档式的并且建立在分布式存储系统之上的 NOSQL 数据库。从其本身的定义我们可以清楚明确三点内容:首先、它是一款非关系型数据库,与传统的关系型数据库完全不同;其次、它存储的数据模型是文档, MongoDB 面向的是集合而不是表,所有的数据存储都以集合为单位,而每个集合里面包含的内容则称为文档,每个文档可以大致认为是个 JSON 数据模型;最后、它是建立在分布式存储系统之上的数据库。

国内很多人觉得是 “ 芒果数据库 ” ,其实不是。 Mongo 是 humongous 的中间部分,所以 MongoDB 可以翻译成巨大无比的或者是海量数据库,可见创始人之雄心。

MongoDB 于 2017-2019 连续 3 年在 DB-Engine 上排名第 5 ,文档类数据库第 1 。

MongoDB 于 2017 年在纳斯达克上市,当日收于 32.07 美元,比 24 美元的 IPO 价格高出 34% 。

2. MongoDB 的发展历史?

2007 年, Dwight Merriman, Eliot Horowitz 和 Kevin Ryan 成立 10gen 软件公司。

2009 年, 10gen 开发出了 MongoDB 的雏形并将它开源以及正式命名为 MongoDB ,同时成立开源社区。

2011 年, MongoDB 上线第一个云服务。

2012 年, MongoDB 2.1 开发分支发布, MongoDB 2.0.6 发布。

2013 年, MongoDB 2.4.3 发布, MongoDB 2.4.6 发布, MongoDB 2.4.8 发布。

2017 年, MongoDB 3.0.1 发布。

2018 年, MongoDB 4.0.2 发布,支持多文档事务。

2019 年, MongoDB 4.2.0 发布,引入分布式事务。

3. MongoDB 的数据模型特点?

一个 MongoDB 数据库服务可以有建立多个数据库,每个数据库可以有多张表,表名叫 Collection ,每个 collection 可以存放多个文档 Document ,每个文档都以 BSON ( Binary Jison )的形式存放于硬盘中,因此可以存储比较复杂的数据类型。文档中保存到数据类型可以为: Null 、 Boolean 、 String 、 Object 、 32 位整数、 64 位整数、 64 位浮点数、日期、正则表达式、 JS 代码、二进制数据、数组、内嵌文档、最大值、最小值、未定义类型。如果用图来表示 MongoDB 的数据结构模型,如图 3.1 所示:

图 3.1 MongoDB 数据结构模型


(1). MongoDB 逻辑对象,从大到小分为数据库、集合、文档、字段、自动标识。例如定义一个学生的文档可以定义为:

(2). MongoDB 数据对象的文档关系模型,包括内嵌 & 引用。引用( References )存储数据之间的关系,包括从一个文档链接或引用到另外一个文档。这样应用程序就解决了访问关联数据的问题,一般来说,这些都是规范数据的数据模型。嵌入式文档通过存储相关的数据在一个文档结构中来捕获数据之间的关系。 MongoDB 文档可以在当前文档的字段或数组中嵌入文档作为子文档。这些非规范化数据模型允许应用程序检索和操作相关的数据在一个单一的数据库操作。例如以上的学生的关联文档,我们分别通过引用和嵌套两种方式来表达其关系。如下展示:

(3). 文档树模型通常有 3 种方式:父文档引用、子文档引用、祖先数组。通俗来讲,数据库当中的文档表示的是应用场景当中的对象,那么这些对象就会有树状的关系结构。例如:图书可以分为社科类、工具类、考试类、文学类等,文学类又分为小说类、散文类、哲学类、历史类等,历史类又可以分为唐、宋、元、明等等。同样在 MongoDB 当中的数据对象也会有这样的树状结构。

我们通过以上的方式就将以图书信息为数据对象插入到我们的 MongoDB 当中,自然在数据库当中就形成了一棵文档树。那么在数据查询以及其他操作的时候我们就可以通过树结构特点,引用文档的父节点、子节点以及从根节点到自己的树的全路径信息。也就是我们所述的父文档引用、子文档引用以及祖先数组的概念。

4. MongoDB 的系统架构?

关于 MongoDB 的体系架构,我们先从最简单的系统架构开始了解。那么数据库的整体逻辑体系架构包括:数据库实例、数据库、集合、文档、字段等。

图 4.1 MongoDB 单实例逻辑架构
磁盘文件经过加载之后后形成 MongoDB 实例,一个 MongoDB 实例中可以存放多个数据库(图中的 MongoDB 数据库 1 、 MongoDB 数据库 2 、 MongoDB 数据库 3 ),数据库中存放的是一个个 Collection (集合,对应关系型数据库的 table ),集合中又存放 Document (文档,对应关系型的记录), Document 中存放 Field (字段,对应关系型数据库列)。

在了解了 MongoDB 单实例逻辑架构基础之上,接下来我们来看 MongoDB 的数据复制架构。它是保障 MongoDB 实现数据保护的重要基础条件。如图 4.2 所示:

图 4.2 MongoDB 数据复制架构
复制集( Replica Set )是 MongoDB 的数据复制架构。通常是三个对等的节点构成一个复制集,有 Primary 和 Secondary 两种角色,其中 Primary 负责读写请求, Secondary 负责读请求,可以通过配置实现。 Primary 和 Secondary 节点之间在数据写入过程当中实现数据的异步复制。节点之间通过 Heartbeat 实现健康侦测,当 Primary 失败,集群可以通过多数派选举新的 Primary ,并且实现 Failover 机制。

复制集的架构解决了数据保护的问题,但是始终没有解决数据量大的情况下带来的性能瓶颈问题,也无法解决集群横向扩展的问题。所以在了解了 MongoDB 数据复制架构基础之上,我们再来看现实场景当中使用比较多的相对比较复杂的分切分布式集群架构,如图 4.3 所示:

图 4.3MongoDB 分片分布式集群架构
从图示架构可以看出,分片集群的优势在于提供类似线性增长的架构,提高数据可用性,提高大型数据库查询服务器的性能。当 MongoDB 单点数据库服务器存储成为瓶颈、单点数据库服务器的性能成为瓶颈或需要部署大型应用以充分利用内存时,可以使用分片技术。

整体架构有几个重要的组件:切片( Shard )、配置服务器( ConfigServer )、路由( Query Router )。那么他们的逻辑关系又是什么样的呢?各自承担了什么的角色呢?

1). Shard : 用于存储实际的数据块,一个切片服务器角色可由几台机器组成,防止主机单点故障。

2). Config Server : MongoDB 实例,存储了整个 ClusterMetadata ,其中包括 chunk 信息。

3). Query Routers :客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。

基于以上组件功能角色,我们来分析客户端的访问路径为:首先、客户端访问路由( Query Router )的统一接口层,由路由层将数据请求发送到特定的配置服务器( ConfigServers );接着,由配置服务器查询本地的元数据信息定位到要访问的数据在哪个切片服务器( Shard )上;最后,客户端直接访问到切片服务器的具体位置,获取自己所需的数据信息。

MongoDB 的数据划分,是以集合级别为标准。分片通过 Shard Key 来划分集合数据。具体切片的策略可以是通过数据的范围划分来切分,也可以通过哈希策略来切分,具体需要考虑到数据的特点和集群数据访问的效率。

5. MongoDB 的存储引擎?

数据库的存储引擎作为数据库的重要组件,决定了数据如何写入数据、如何持久化存储数据。

MongoDB 3.0 引入了插件式存储引擎 API ,为第三方的存储引擎厂商加入 MongoDB 提供了方便,目前除了早期的 MMAP 存储引擎外,还有 Wired Tiger 和 In-Memory Storage Engine 等,前者更是在被 MongoDB 公司收购后更是直接引入到了 MongoDB 3.0 版本中,在 3.2 版本中的默认存储引擎是 Wired Tiger 。对于 Wired Tiger 存储引擎,其内部架构如图 5.1 所示:

图 5.1 MongoDB 存储引擎架构

按照 Mongodb 默认的配置, WiredTiger 的写操作会先写入 Cache ,并持久化到 WAL(Write ahead log) ,每 60s 或 log 文件达到 2GB 时会做一次 Checkpoint ,将当前的数据持久化,产生一个新的快照。 Wiredtiger 连接初始化时,首先将数据恢复至最新的快照状态,然后根据 WAL 恢复数据,以保证存储可靠性。

Wiredtiger 的 Cache 采用 Btree 的方式组织,每个 Btree 节点为一个 Page , Root Page 是 Btree 的根节点, Internalpage 是 Btree 的中间索引节点, Leaf Page 是真正存储数据的叶子节点; Btree 的数据以页为单位按需从磁盘加载或写入磁盘。 Wiredtiger 采用 Copy on Write 的方式管理修改操作( insert 、 update 、 delete ),修改操作会先缓存在 cache 里,持久化时,修改操作不会在原来的 Leaf Page 上进行,而是写入新分配的 Page ,每次 CheckPoint 都会产生一个新的 Root Page 。

基于 Wiredtiger 这种存储引擎的架构特点,也赋予其有如下几个特性:

1). 文档级别的锁: MongoDB 在执行写操作时, WiredTiger 在文档级别进行并发控制,就是说,在同一时间,多个写操作能够修改同一个集合中的不同文档;当多个写操作修改同一个文档时,必须以序列化方式执行;这意味着,如果该文档正在被修改,其他写操作必须等待,直到在该文档上的写操作完成之后,其他写操作相互竞争,获胜的写操作在该文档上执行修改操作。

2). 检查点机制:类似关系数据库的 CheckPoint ,在 Checkpoint 操作开始时, WiredTiger 提供指定时间点( point-in-time )的数据库快照( Snapshot ),该 Snapshot 呈现的是内存中数据的一致性视图。当向 Disk 写入数据时, WiredTiger 将 Snapshot 中的所有数据以一致性方式写入到数据文件中。同样 MongoDB 借助 Journal 日志文件也可以还原数据。

3). 内存使用:从 MongoDB 3.2 版本开始, WiredTiger 内部缓存的使用量,默认值是: 1GB 或 60% of RAM - 1GB ,取两值中的较大值(不同版本会有区别,具体参考版本配置文件说明);文件系统缓存的使用量不固定, MongoDB 自动使用系统空闲的内存。

6. MongoDB 的索引类型 ?

MongoDB 支持多种类型的索引,包括单字段索引、复合索引、多键索引、文本索引等,每种类型的索引有不同的使用场合。

1). 单字段索引与符合索引比较好理解,是以单个字段或者多个字段为主健建立的索引。复合索引能满足的查询场景比单字段索引更丰富,不仅能满足多个字段组合起来的查询,比如 db.person.find( {age:20 , name: "Lili"} ) ,也能满足所以能匹配符合索引前缀的查询,这里 {age: 2} 即为 {age: 2, name: } 的前缀, 所以类似 db.person.find( {age:20} ) 的查询也能通过该索引来加速。

2). 多键索引:当索引的字段为数组时,创建出的索引称为多 Key 索引,多 Key 索引会为数组的每个元素建立一条索引,例如 { name: “Lili”, Class : “02”, Choice: ["Football, BasketBall, Music…"]} 。我们可以以 Choice 数组字段建立一个多键索引,可以查询选择了某一系列组合选修课的同学。

3). 哈希索引:是指按照某个字段的 Hash 值来建立索引,目前主要用于 MongoDB 切片集群。哈希索引只能满足字段完全匹配的查询,不能满足范围查询等。

4). 地理位置索引:能很好的解决 O2O 的应用场景,比如查找附近的美食等类似应用需求。

5). 文本索引:能解决快速文本查找的需求,比如有一个博客文章集合,需要根据博客的内容来快速查找,则可以针对博客内容建立文本索引。

7. MongoDB 适用场景?

要谈 MongoDB 的适用场景,首先要知道 MongoDB 作为文档型数据库的最大优势在于什么?总结来看个人觉得 MongoDB 的优势在于其数据模型的灵活性、架构的扩展性以及特殊的存储引擎。使得它在 NOSQL 数据库当中最接近关系数据库的数据特点,同时又保障了 NOSQL 数据库的扩展性集群优势,总结来看,有以下几点:

事务支持MongoDB 目前只支持单文档事务,复杂事务场景不适合。
灵活的文档模型JSON 格式存储最接近真实对象模型,对开发者友好。
切片集群架构分布式扩展。
多引擎支持mmapv1、wiredtiger、in-memory满足各种场景需求。
强大的索引支持地理位置索引、文本索引等特殊场景。

那么了解了 MongoDB 的优势,接下来就是从什么维度去判断场景是否适合使用 MongoDB ,那么我们觉得应该从以下几个方面去判断。

1). 应用不需要事务及复杂 join 支持,如果需要,那么肯定不是 MongoDB 擅长的。

2). 数据模型后期结够会不会变化?结构是否能统一?也就是说用 JSON 来表达式不是最佳选择?

3). 应用发展迅速,数据量到 PB 级别?需要能快速水平扩展?这也是 MongoDB 的擅长项。

4). 特殊索引解决的特殊场景问题?地理索引、文档索引等能解决的特殊场景问题。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

3

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广