MongoDB做为现在主流的文档型数据库,在大小公司都有普遍的应用。相信对服务有可用性要求的公司,都或多或少会用到复制集功能。复制集正是MongoDB提供的一整套高可用性的解决方案。现阶段不少文章都是讲述如何建立一个副本集,可是对副本集的原理不多提示。因此,第一篇文章将详尽的阐述其中各个概念,以便你对复制集功能有个总体的了解。web
如今假设你运行一个web服务,服务后面连着一个MongoDB实例。若是这个时候实例挂掉了,整个web服务都将不可用,这在生产环境必定是不容许的。那么若是咱们运行多个MongoDB的实例,挂掉一个由另一个顶上,整个服务的可用性都将大幅提升。这样的多个实例的集合就称为复制集。固然复制集上的实例,都保存着相同的数据。redis
MongoDB实现的复制集是主从架构,以下图所示 算法
在复制集中存在两种不一样类型的节点分别是Primary
(后文用主节点指代)以及Secondary
(后文用从节点指代)。数据库
在一个复制集中只能存在一个主节点,但能够存在多个从节点。从节点不可接受写入操做,主节点接受写入操做,经过oplog
的形式,将数据同步给从节点。 oplog
是数据的写入的日志。你插入一条记录,那么日志就会增长一行插入操做。从节点拿到日志,在本身服务上面重放这个操做,就实现了数据的同步。bash
当咱们的主节点由于意外状况挂掉,其余从节点会选举出一个节点做为新的主节点。 架构
Raft
(
zh.wikipedia.org/wiki/Raft)。
通常来讲选举会发生在如下几种状况里面:分布式
当咱们只有一台MongoDB实例的时候,客户端的一个插入记录,写入成功直接返回success。可是,如今咱们有一个复制集,那么客户端的写入操做怎么才算成功写入呢?ui
这就要提到MongoDB的写入配置Write Concern
。Write Concern
是这样一种k,v结构{ w: <value>, j: <boolean>, wtimeout: <number> }
。spa
w表示须要多少个节点确认才算写入成功,默认值为1({'w': 1}
)。表示写入Primary
节点后就算写入成功。若是填n
表示须要写入n个节点,才可以算写入成功。日志
w还有另外一种选项majority
,表示写入大部分节点算成功写入。举个例子,如今有3个节点参与选举投票,那么成功写入2个就算写入成功。
j表示是否须要成功写入journal files
。
表示超时时间,这里须要额外注意,在有的临界点写入成功也有可能返回超时。可是MongoDB是不会去回滚写入成功的数据的。
Write Concern
能够直接修改集群配置
cfg = rs.conf()
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)
复制代码
也能够增长
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: "majority" , wtimeout: 5000 } }
)
复制代码
第二个参数作单独的配置。
MongoDB的从节点能够大体分为五类:
这类从节点属于priority
为1,能够正常的选举,复制数据。
这类节点只能复制数据,不能被选举为主节点,也不能触发选举的开始。这类节点一般做为跟随节点。所谓跟随节点,只存储数据,当普通节点宕机时,能够迅速替换到主节点。
隐藏节点对于客户端是不可见的,隐藏节点的priority必定要为0.
延迟节点不会当即同步主节点的数据,会有个时间上的延迟。比方说7点主节点写入一条数据,8点延迟节点才会同步这点数据。延迟节点最好设置为隐藏节点,以避免客户端读取到脏数据。延迟节点的做用,主要是做为备份和回滚使用。
这类节点不含数据,仅仅是做为投票使用。有的时候咱们可能有4个节点用来投票,可是投票节点数须要奇数个,就能够部署一台仲裁者,使投票节点数为奇数。
和redis
类似,数据同步遵循两种形式,当新节点加入集群时,为把数据全量传输过去。第一次同步事后,会根据oplog
进行操做重放,增量更新。