Mongodb是一个基于分布式文件存储内存型非关系型数据库(NoSQL),由C++编写。

架构模式

  1. 单库:一般测试用,没有高可用,容易部署
  2. 主从复制:这种架构至少需要两台服务器构成一主一备,也可以支持一主多备。当然,也可以通过同一台服务器的多个实例配置成一主一备或一主多备,只不过灵活性,备份,高可用,扩展性都不好。
  3. 副本集(Replica set):也叫复制集。副本集就是一个可以自动故障切换的主备库集群。和主从架构的最大区别就是没有一个固定的主库(primary),而是由集群选举一个主库,当前的主库挂掉,集群会自动从备库(secondary)中选举一个转变为主库。primary负责读写请求,secondary负责读请求。是一个HA架构,解决了单点故障的问题。
  4. 分片集群(Sharding cluster):mongo进行数据水平扩展的常用手段。复制集架构的最大的缺点就是集群容量受限于单个节点的磁盘大小,如果数据量不断增加,对它进行扩容非常困难,所以使用Sharding模式来解决这个问题。原理:将整个集合(colletion)的数据根据sharding key,被sharding到多个mongo节点上,即每个节点持有colletion的一部分数据,这个集群持有全部数据,所以原则上sharding可以支持数TB的数据。

分片集群(Sharding cluster)

分片几个基本概念

  • 分片(shard):每个分片包含了分片数据的一个子集,每个分片可以作为一个副本集部署。
  • mongos路由:路由器的角色,提供者客户端应用和分片集群的接口。
  • 配置服务器(config servers):配置服务器存储着集群的元数据和配置设置,MongoDB3.4之后,配置服务就必须部署为副本集
分片集群示意图

分片主键

为了能在集合中分配文档,MongoDB使用分片主键分割集合。分片主键由不重复的字段或字段集合组成。

对于一个集合分片时,要选择一个主键,分片主键在分片后就不能修改。一个分片只能有一个分片主键

对于非空集合进行分片,集合必须有一个以分片主键开头的索引。对于空集合,如果集合对于分片主键没有一个合适的索引,MongoDB将创建索引。

区块

MongoDB分割分片数据到区块,每一个区块包含基于分片主键的左闭右开的区间范围。

分片的优点

MongoDB通过集群中的分片分配读写的工作负载,允许每一个分片处理集群中的一部分操作,读写可以通过添加分片进行横向扩展。包含分片主键或组合前缀的查询,mongos可以定位这个查询到特定的分片或分片子集上,这个定位操作比广播到所有分片的效率高得多。

随着数据的增长,增加额外的分片可以增加集群的存储能力。

即使集群中的一个或多个分片不可用,集群也可以继续执行一部分可用的读写操作。在宕机期间,可用分片的读写操作还是可以被成功处理的。每一个分片部署成副本集,可以提供可增长的冗余和高可用。

分片的缺点

分片集群的基础需求需要小心的计划,执行和维护。谨慎的考虑分欧安主键是确保集群性能所必须的。分片之后,分片主键就不能更改,也不能使集合不分片。如果查询不包含分片主键或组合主键的前缀,mongos将进行广播,查询所有分片,这些查询将花费很长时间。

分片与不分片

一个数据库可以由分片集合和不分片集合的混合。分片集合通过集群中的分片进行分割和分配,不分片集合存储在基础分片中。每个数据库都有一个自己的基础分片。

连接分片集群

客户端必须通过mongos路由和分片中或不分片的集合进行交互。客户端是不能连接一个单独的分片进行操作的。

连接分片集群

持久化原理

MongoDB具有高度可配置的持久化设置,从完全没有任何保证到完成持久化。

mongodb和mysql不同,mysql的每一次更新操作都会直接写入磁盘,但是mongo不会,作为内存型数据库,数据操作会先写入内存,然后再持久化到磁盘。

mongodb在启动时,专门初始化一个线程不断循环,用于一定时间周期内来从defer队列中获取要持久化的数据并写入磁盘的 joural (日志)和 mongofile(数据)中,当进行CUD操作时,记录都是被放入defer队列中,以提供延时批量(groupcommit)提交写入。所以时间周期参数是个需要认真考虑的参数,系统是90毫秒,太低会导致频繁的磁盘操作,太高有可能导致业务系统宕机时数据丢失。