MongoDB

来自智得网
跳转至: 导航、​ 搜索

简介

mongoDB是流行的文档型数据库,使用方式类似于关系型数据库,其存储模型bson在JSON基础上进行了扩展,介于结构化存储和非结构化存储之间。

mongoDB具有以下特点:

  • 面向集合存储,易存储对象类型的数据。
  • 模式自由。
  • 支持动态查询。
  • 支持完全索引,包含内部对象。
  • 支持查询。
  • 支持复制和故障恢复。
  • 使用高效的二进制数据存储,包括大型对象(如视频等)。
  • 自动处理碎片,以支持云计算层次的扩展性
  • 支持python,java,C++,php等语言的驱动程序,社区中也提供了对 Erlang,.NET等平台的驱动程序。
  • 可通过网络访问。
MongoDB存储的概念

mongoDB的概念和数据库概念可以逐级类比。

MongoDB概念 Database概念 概念异同
database database 基本一致,database是一个物理层的概念,一个database可以包含若干种结构化的数据。
collection table table是有明确schema的,但collection是半结构化的。
document 记录 都由多个列/字段构成。
field field 具体一条记录的某个字段称为field
_id 主键 主键 保证文档的唯一性
reference 外键 由客户端(driver)自动进行关联查询、转换的一个特殊类型。不具备外键的约束性
index index 概念基本一致
transaction transaction MongoDB 4.0 版本开始,提供了对于事务的支持

存储模型

mongoDB数据库中的数据采用bson的方式存储,bson是从json引申出来的概念,含义为binary JSON。从本质上来看,bson是json的一个超集,除了字符串,整形,bool之外,bson还支持时间类型以及字节数组。

JSON BSON
编码 UTF-8 String Binary
数据结构 String, Boolean, Number, Array String, Boolean, Number (Integer, Float, Long, Decimal128...), Array, Date, Raw Binary
可读性 机器和可视化 机器

BSON数据结构以及和json的关系如下所示:

{"hello": "world"} 
\x16\x00\x00\x00           // total document size
\x02                       // 0x02 = type String
hello\x00                  // field name
\x06\x00\x00\x00world\x00  // field value
\x00                       // 0x00 = type EOO ('end of object')

索引

mongoDB的索引分为几类:

  • 单键索引

单键索引就是单独的字段作为索引列,mongoDB所有的collection默认都会有一个单键索引_id。_id一般是通过客户端生成,当写入数据不包含该字段的时候,服务端进行生成。_id由12个字节组成,依次是4个字节的Unix时间戳,3个字节的机器ID,2字节的进程ID,3个字节的计数器。

  • 复合索引

复合索引是指包含多个字段的索引,用法和单键索引类似。

mongodb的索引采用B+树进行存储。出了普通的B+索引之外,MongoDB还支持以下的索引结构:

  • 哈希(HASH)索引,哈希是另一种快速检索的数据结构,MongoDB 的 HASH 类型分片键会使用哈希索引。
  • 地理空间索引,用于支持快速的地理空间查询,如寻找附近1公里的商家。
  • 文本索引,用于支持快速的全文检索
  • 模糊索引(Wildcard Index),一种基于匹配规则的灵活式索引,在4.2版本开始引入。

部署架构

单机架构

standalone架构,mongoDB支持完备的查询语法(除了join之外的几乎所有sql操作),支持丰富的二级索引,支持查询优化器以及通过explain查询优化器的详细信息

WiredTiger支持ACID事务,可以保证数据和索引的一致性。

主从架构

replica set架构,主从架构的mongodb支持自动切主的功能。

一组mongoDB存储服务器构成一个副本集,副本集中会有一个用于处理写操作,称作primary节点,其余都是从节点(secondary)。

primary节点的选举基于raft协议。

mongoDB副本集之间数据同步依赖的日志成为oplog,节点从同步源拉取oplog,写入自身的数据集,然后再写入自己的oplog。

为了实现写入数据集的原子性/幂等性,每一条oplog不是和操作关联的,而是只会包含一个文档的操作,例如通过db.**.remove()操作从文档中删除100条记录,在oplog中100条操作日志。

当新的oplog加入副本集的时候,会进行初始化同步,因为是全量同步,数据量较大,所以耗费时间较长,此时有一个风险是oplog日志的大小是固定的,所以早期数据可能已经被覆盖,导致新的副本无法获取正确的数据。所以主节点的oplog一般要求存储2-3天的全量数据。

如果在复制没有完成的时候发生了网络分区,可能会有从节点在缺失部分数据的情况下成为新的主节点,当旧的主节点恢复的时候,会把这些新的主节点上缺失的数据进行回滚。

分片集群架构

shards架构

Mongodb的自动分片机制

分片是指把数据分布到不同存储上的过程,通用会用术语partitioning表示这个概念。大部分存储支持手动分片,例如mysqles等,但是mongoDB支持自动分片,这种方式试图将存储的部署架构和应用程序彻底分离。

使用数据分片的存储都需要实现路由逻辑,路由逻辑分为两种实现方式,一种是客户端路由,即通过存储的SDK实现路由功能,另外一种是使用单独的路由服务器。因为mongoDB的分片是支持自动调整的,所以只能由单独的路由服务器来实现路由功能。路由节点一般称为mongod。

因为分片会增加系统的复杂度,建议只有在内存,硬盘等系统资源出现容量瓶颈的情况下启用。

分片之后,每个mongos都需要能够根据分片健查询数据,也就是从分片健到数据位置的索引,mongos通过维护数据块和分片的映射来追踪集群数据。

均衡器负责数据的前一,它会定期检查不同分片是否存在数据倾斜,即不平衡问题,如果存在,就会进行数据迁移。

MongoDB目前支持两种分片算法:

根据范围进行分片,实现较为简单,可以很好的支持主键的范围查询。

按照Hash值分片,数据分布较为均衡,但是范围查询需要merge多个分片的数据。