1 基本概念
1.1 副本集与分片集
副本集与分片是mongo数据库2种集群搭建方式
副本集(Replica Set)是指同一份数据被保存到N个机器上,每个机器上都是想同的数据,写操作发生在主库,从库同步主库的OpLog日志。
分片(shard)是指一份数据被分离开保存到N个机器上,N个机器上的数据组合起来是一份数据。
1.2 副本集成员
1.2.1 成员角色
成员可以是以下某种角色:
|
成为primary |
对客户端可见 |
参与投票 |
延迟同步 |
复制数据 |
Default |
√ |
√ |
√ |
∕ |
√ |
Secondary-Only |
∕ |
√ |
√ |
∕ |
√ |
Hidden |
∕ |
∕ |
√ |
∕ |
√ |
Delayed |
∕ |
√ |
√ |
√ |
√ |
Arbiters |
∕ |
∕ |
√ |
∕ |
∕ |
Non-Voting |
√ |
√ |
∕ |
∕ |
√ |
表:副本集角色属性
1.2.2 成员优先级
在副本集中,每个成员都有优先级,它可以帮助决定选举出primary。默认情况下,所有的成员的优先级都为1。设置优先级为0不能成为主节点,但是可以参与选举、数据复制。
1.3 心跳与同步机制
1.3.1 心跳机制
mongodb节点会向副本集中的其他节点每两秒就会发送一次pings包,如果其他节点在10秒钟之内没有返回就标示为不能访问。每个节点内部都会维护一个状态映射表,表明当前每个节点是什么角色、日志时间戳等关键信息。如果是主节点,除了维护映射表外还需要检查自己能否和集群中内大部分节点通讯,如果不能则把自己降级为secondary只读节点。
1.3.2 同步机制
副本集同步分为初始化同步和keep复制。初始化同步指全量从主节点同步数据,如果主节点数据量比较大同步时间会比较长。而keep复制指初始化同步过后,节点之间的实时同步一般是增量同步。初始化同步不只是在第一次才会被触发,有以下两种情况会触发:secondary第一次加入,这个是肯定的。secondary落后的数据量超过了oplog的大小,这样也会被全量复制。oplogSize 可以通过–oplogSize设置大小,对于linux 和windows 64位,oplog size默认为剩余磁盘空间的5%。
secondary不会从delayed和hidden成员上复制数据。如果同步操作30秒都没有反应,则会重新选择一个节点进行同步。
1.4 故障切换与恢复
副本集能够自动进行故障切换恢复。如果primary掉线或者无反应且多数的副本集成员能够相互连接,则选出一个新的primary。
在多数情况下,当primary宕机、不可用或者是不适合做primary时,在没有管理者干预的几秒后会进行故障切换。如果MongoDB部署没有如预期那样进行故障切换,则可能出现了问题:剩余的成员个数少于副本集的一半;没有成员有资格成为primary。
所有的Secondary都宕机、或则副本集中只剩下一个节点,则该节点只能为Secondary节点,也就意味着整个集群不能进行写操作(如果应用程序没有设置相应的ReadReference也可能不能进行读取操作),当其他的恢复时,之前的primary节点仍然是primary节点。
当某个节点宕机后重新启动该节点会有一段的时间(时间长短视集群的数据量和宕机时间而定)导致整个集群中所有节点都成为secondary而无法进行写操作(如果应用程序没有设置相应的ReadReference也可能不能进行读取操作)。
2 副本集架构
副本集部署的架构对其容量和性能都有很大影响。大多数产品部署成包含3个优先级为1 的成员就足够了。
如图:
当primary服务异常后,由secondary节点选举出新的primary节点。
当开发一个副本集架构时要注意下面的因素:
a) 确保副本集的成员总能选出一个primary。运行奇数个成员或者运行一个仲裁者(arbiter)+偶数个成员。
b) 分布在不同地理位置的成员,知道“群体”的成员在任意网络分区中的情况。试图确保在主数据中心的成员中选举出primary。
c) 考虑副本集中包含hidden或者delayed成员用于支持专用功能,如备份、reporting和测试。
d) 考虑保留一或者两个位于其他数据中心的成员,同时通过配置确保其不会成为primary。
e) 使用replica set tags创建定制的写规则以确保应用能够控制写操作成功的门限值。使用写规则确保操作在返回成功之前将操作传递给指定的数据中心或不同功能的机器。
2.1 部署策略
不存在一个理想的副本集架构可以满足任意部署环境。
最小的副本集推荐架构为三成员集合,其中一个为primary,另外两个为secondary,secondary在一定情况下可以成为primary。
如果副本集中的成员多于三个,则需要遵照下面的架构条件:
a) 集合中有奇数个参与投票的成员。如果有偶数个投票成员,则部署一个仲裁者将个数变为奇数。
b) 集合中同一时刻最多支持12个成员,但是只有7个成员可以参与投票,3.0版本后成员可以多达50个成员,但是只有7个成员可以参与投票。
c) 如果不想让某些成员在故障切换时成为primary,则将它们的优先级设为0。
d) 集合的多数成员运行在主要的数据中心。
2.2 地理上的分布式集
一个基于地理的分布式副本集可以应对一个数据中心恢复失败的情况。这种集合至少包含了一个在备份数据中心的集合成员。
图:基于地理上的分布式副本集
如果primary掉线,则副本集选出一个新的primary;如果主数据中心和备数据中心连接失败,备数据中心的secondary不能成为primary。如果主数据中心失败,则需要人为的从备数据中心恢复数据。
值得注意的是,这种架构下,必须注意在主数据中心要保持奇数个参与投票的成员,上图中则需要在主数据中心添加一个仲裁者。
3 读写分离
Mongodb默认是primary节点负责所有的读写操作,读操作可以通过配置从secondary节点进读取,但是写操作只能通过primary节点进行。
要在副本集上实现读写分离,我们需要实现以下两步:
a) 在副本节点上设置setSlaveOk;
b) 应用客户端设置ReadReference(读偏好)
设置setSlaveOk方法:
a) 进入shell,执行语句rs. setSlaveOk()
b) 永久设置,修改.mongorc.js,添加rs.slaveOk()。
ReadReference(读偏好)描述了MongoDB客户端是怎样路由读请求到副本集中的成员,模式读偏好为主节点模式。
缺点:除了主节点模式,其他模式返回的可能是过期的数据,因为在异步复制时,从节点中的数据不能反映最近的写入操作;所有的从节点拥有与主节点一样的写入负载,读的加入会增加其负载。
优点:非主节点模式在故障切换时保持可用性;当超过半数节点故障时,剩余节点均为secondary节点。非主节点模式仍然可以提供读服务,主节点模式时将不会提供任何服务。
MongDB驱动支持5中读偏好模式。
读偏好模式 |
描述 |
primary |
默认模式,所有的读操作都从当前副本集主节点 |
primaryPreferred |
多数情况下,从主节点读取数据,但是如果主节点不可用了,会从从节点读取 |
secondary |
所有读操作都从副本集的从节点读取 |
secondaryPreferred |
多数情况下, 从从节点进行读操作,但是如果从节点都不可用了,从主节点读取 |
nearest |
从副本集中延迟最低的成员读取,不考虑成员的类型 |
MongoDB驱动允许客户端应用对于每个连接、每个collection或者每个操作进行读偏好设置,配置多个时执行就近原则。
4 副本集常用操作
移除节点
rs.remove('ip:port');
添加节点
rs.add('ip:port')
重新加载配置
rs.reconfig({配置信息})
查询副本集状态
rs.status()
查询副本集配置信息
rs.config()
添加仲裁者节点
rs.addArb('ip:port')
5 测试环境部署架构