mongodb副本集高可用架构
一、简介
Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点。
Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集,实现数据的高可用。
使用场景
- 数据冗余,用做故障恢复使用,当发生硬件故障或者其它原因造成的宕机时,可以使用副本进行恢复。
- 读写分离,读的请求分流到副本上,减轻主节点的读压力。
一个典型的副本集架构如下图所示:

二、副本集角色
主节点(Primary)
接收所有的写请求,然后把修改同步到所有Secondary。一个Replica Set只能有一个Primary节点,当Primary挂掉后,其他Secondary或者Arbiter节点会重新选举出来一个主节点。
默认读请求也是发到Primary节点处理的,可以通过修改客户端连接配置以支持读取Secondary节点。副本节点(Secondary)
与主节点保持同样的数据集。当主节点挂掉的时候,参与选主。仲裁者(Arbiter)
不保有数据,不参与选主,只进行选主投票。使用Arbiter可以减轻数据存储的硬件需求,Arbiter几乎没什么大的硬件资源需求,但重要的一点是,在生产环境下它和其他数据节点不要部署在同一台机器上。
三、两种架构模式
- PSS
Primary + Secondary + Secondary模式,通过Primary和Secondary搭建的Replica Set
Diagram of a 3 member replica set that consists of a primary and two secondaries.

该模式下 Replica Set节点数必须为奇数,目的是选主投票的时候要出现大多数才能进行选主决策。
- PSA
Primary + Secondary + Arbiter模式,使用Arbiter搭建Replica Set

偶数个数据节点,加一个Arbiter构成的Replica Set
四、选举机制
复制集通过 replSetInitiate 命令或 rs.initiate() 命令进行初始化。
初始化后各个成员间开始发送心跳消息,并发起 Primary 选举操作,获得大多数成员投票支持的节点,会成为 Primary,其余节点成为 Secondary。
config = {
_id : "my_replica_set",
members : [
{_id : 0, host : "rs1.example.net:27017"},
{_id : 1, host : "rs2.example.net:27017"},
{_id : 2, host : "rs3.example.net:27017"},
]
}
rs.initiate(config)
大多数
假设复制集内投票成员(后续介绍)数量为 N,则大多数为 N/2 + 1,当复制集内存活成员数量不足大多数时,整个复制集将无法选举出 Primary,复制集将无法提供写服务,处于只读状态。
关于大多数的计算如下表所示
| 投票成员数 | 大多数 | 容忍失效数 |
|---|---|---|
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 3 | 2 |
Mongodb副本集的选举基于Bully算法,这是一种协调者竞选算法,详细解析可以参考这里
Primary 的选举受节点间心跳、优先级、最新的 oplog 时间等多种因素影响。官方文档对于选举机制的说明
特殊角色
Arbiter
Arbiter 节点只参与投票,不能被选为 Primary,并且不从 Primary 同步数据。
当节点宕机导致复制集无法选出 Primary时,可以给复制集添加一个 Arbiter 节点,即使有节点宕机,仍能选出 Primary。
Arbiter 本身不存储数据,是非常轻量级的服务,当复制集成员为偶数时,最好加入一个 Arbiter 节点,以提升复制集可用性。Priority0
Priority0节点的选举优先级为0,不会被选举为 Primary。
比如你跨机房 A、B 部署了一个复制集,并且想指定 Primary 必须在 A 机房,这时可以将 B 机房的复制集成员 Priority 设置为0,这样 Primary 就一定会是 A 机房的成员。
(注意:如果这样部署,最好将大多数节点部署在 A 机房,否则网络分区时可能无法选出 Primary。)Vote0
Mongodb 3.0里,复制集成员最多50个,参与 Primary 选举投票的成员最多7个,其他成员(Vote0)的 vote 属性必须设置为0,即不参与投票。Hidden
Hidden 节点不能被选为主(Priority 为0),并且对 Driver 不可见。
因 Hidden 节点不会接受 Driver 的请求,可使用 Hidden 节点做一些数据备份、离线计算的任务,不会影响复制集的服务。Delayed
Delayed 节点必须是 Hidden 节点,并且其数据落后与 Primary 一段时间(可配置,比如1个小时)。
因 Delayed 节点的数据比 Primary 落后一段时间,当错误或者无效的数据写入 Primary 时,可通过 Delayed 节点的数据来恢复到之前的时间点。
触发选举条件
- 初始化一个副本集时。
- 从库不能连接到主库(默认超过10s,可通过heartbeatTimeoutSecs参数控制),由从库发起选举
- 主库放弃primary 角色,比如执行rs.stepdown 命令
Mongodb副本集通过心跳检测实现自动failover机制,进而实现高可用

五、数据同步
Primary 与 Secondary 之间通过 oplog 来同步数据,Primary 上的写操作完成后,会向特殊的 local.oplog.rs 特殊集合写入一条 oplog,Secondary 不断的从 Primary 取新的 oplog 并应用。
因 oplog 的数据会不断增加,local.oplog.rs 被设置成为一个 capped 集合,当容量达到配置上限时,会将最旧的数据删除掉。
另外考虑到 oplog 在 Secondary 上可能重复应用,oplog 必须具有幂等性,即重复应用也会得到相同的结果。
如下 oplog 的格式,包含 ts、h、op、ns、o 等字段。
{
"ts" : Timestamp(1446011584, 2),
"h" : NumberLong("1687359108795812092"),
"v" : 2,
"op" : "i",
"ns" : "test.nosql",
"o" : { "_id" : ObjectId("563062c0b085733f34ab4129"), "name" : "mongodb", "score" : "100" }
}
| 属性 | 说明 |
|---|---|
| ts | 操作时间,当前 timestamp + 计数器,计数器每秒都被重置 |
| h | 操作的全局唯一标识 |
| v | oplog 版本信息 |
| op | 操作类型 |
| op.i | 插入操作 |
| op.u | 更新操作 |
| op.d | 删除操作 |
| op.c | 执行命令(如 createDatabase,dropDatabase) |
| op.n | 空操作,特殊用途 |
| ns | 操作针对的集合 |
| o | 操作内容 |
| o2 | 操作查询条件,仅 update 操作包含该字段。 |
Secondary 初次同步数据时,会先执行 init sync,从 Primary(或其他数据更新的 Secondary)同步全量数据,
然后不断通过执行tailable cursor从 Primary 的 local.oplog.rs 集合里查询最新的 oplog 并应用到自身。
异常回滚
当 Primary 宕机时,如果有数据未同步到 Secondary,当 Primary 重新加入时,如果新的 Primary 上已经发生了写操作,则旧 Primary 需要回滚部分操作,以保证数据集与新的 Primary 一致。
旧 Primary 将回滚的数据写到单独的 rollback 目录下,数据库管理员可根据需要使用 mongorestore 进行恢复
六、读写配置
Read Preference
默认情况下,复制集的所有读请求都发到 Primary,Driver 可通过设置 Read Preference 来将读请求路由到其他的节点。
- primary:默认规则,所有读请求发到 Primary;
- primaryPreferred:Primary 优先,如果 Primary 不可达,请求 Secondary;
- secondary:所有的读请求都发到 secondary;
- secondaryPreferred:Secondary 优先,当所有 Secondary 不可达时,请求 Primary;
- nearest:读请求发送到最近的可达节点上(通过 ping 探测得出最近的节点)。
关于read-preference
Write Concern
默认情况下,Primary 完成写操作即返回,Driver 可通过设置 Write Concern (参见这里)来设置写成功的规则。
如下的 write concern 规则设置写必须在大多数节点上成功,超时时间为5s。
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: majority, wtimeout: 5000 } }
)
参考文档
搭建高可用mongodb集群
http://www.lanceyan.com/tech/mongodb_repset2.html
深入浅出Mongodb复制
http://www.mongoing.com/archives/5200
mongodb副本集原理
https://yq.aliyun.com/articles/64?spm=0.0.0.0.9jrPm8
副本集主备切换
https://docs.mongodb.com/manual/tutorial/force-member-to-be-primary/index.html
mongodb副本集高可用架构的更多相关文章
- MongoDB复制集高可用选举机制(三)
复制集高可用选举机制 在上一章介绍了MongoDB的架构,复制集的架构直接影响着故障切换时的结果.为了能够有效的故障切换,请确保至少有一个节点能够顺利升职为主节点.保证在拥有核心业务系统的数据中心中拥 ...
- 生产环境下搭建mongodb复制集高可用环境(python)
环境描述:有三台ubuntu服务器,,每台服务器上已经有mongodb实例.创建3个mongo2.4的新实例,分别作为三个复制集节点,同时保证了当前单节点环境的稳定 3台服务器都已经有单个mongo实 ...
- MongoDB副本集及C#程序的连接配置
1.副本集 高可用是绝大多数数据库管理系统的核心目标之一.如果要想生产数据在发生故障后依然可用,就需要确保为生产数据库多部署一台服务器.MongoDB副本集提供了数据的保护.高可用和灾难恢复的机制. ...
- NoSQL数据库Mongodb副本集架构(Replica Set)高可用部署
NoSQL数据库Mongodb副本集架构(Replica Set)高可用部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. MongoDB 是一个基于分布式文件存储的数据库.由 C ...
- MongoDB 3.4 高可用集群搭建(二)replica set 副本集
转自:http://www.lanceyan.com/tech/mongodb/mongodb_repset1.html 在上一篇文章<MongoDB 3.4 高可用集群搭建(一):主从模式&g ...
- MongoDB高可用架构:Replica Sets+Sharding
MongoDB的sharding解决了海量存储和动态扩容的问题.但是遇到单点故障就显得无能为力了.MongoDB的副本集可以很好的解决单点故障的问题.所以就有了Sharding+Replica Set ...
- 数据库高可用架构(MySQL、Oracle、MongoDB、Redis)
一.MySQL MySQL小型高可用架构 方案:MySQL双主.主从 + Keepalived主从自动切换 服务器资源:两台PC Server 优点:架构简单,节省资源 缺点:无法线性扩展,主从失 ...
- [MongoDB] 高可用架构方案
一.缘由: 众所周知,Mongodb是在高速发展期,一些特性架构难免会发生变化.这里就总结下,我目前所知道的Mongodb 的高可用架构都有哪些.目前Mongodb版本3.2. 二.结构介绍: 1.R ...
- [转]数据库高可用架构(MySQL、Oracle、MongoDB、Redis)
一.MySQL MySQL小型高可用架构 方案:MySQL双主.主从 + Keepalived主从自动切换 服务器资源:两台PC Server 优点:架构简单,节省资源 缺点:无法线性扩展,主从失 ...
随机推荐
- firefox添加post插件
附加组件 - > 插件 -> 搜索RESTClient
- linux磁盘满了的处理
1.查看磁盘使用情况 cd / df -h 如果 总量Size和Used一样,按就证明磁盘满了 2.查看当前文件下每个文件大小 du -sh * 一层一层去查,就可以查到占用空间最大的那个文件及产生 ...
- 接口测试——postman & jmeter
新名词: 自动化测试:写代码帮你测试 接口:是一个抽象的概念,一种交互关系. 抓包:拦截请求. 接口测试:就是功能测试,比后者还简单. 需要有测试文档,包括项目.模块.URL.请求方式.参数.参数说明 ...
- C#语言struct结构体适用场景和注意事项
在C#语言中struct结构体和class之间的区别主要是值类型和引用类型的区别,但实际上如果使用不当是非常要命的.从Win32时代过来的人对于struct一点不感觉陌生,但是却反而忽略了一些基本问题 ...
- iphone 屏蔽系统自动更新,消除设置上的小红点
苹果ios系统的更新频率大家应该都知道,一般来说1个月就会来次更新.这一点让很多人讨厌.主要原因还是iPhone会自动下载更新包,然后一直不停地提示你是否安装更新,问题是我们还找不到关闭提醒和关闭自动 ...
- 【尺取法】Jurisdiction Disenchantment
[尺取法]Jurisdiction Disenchantment PROBLEM 时间限制: 1 Sec 内存限制: 128 MB 题目描述 The Super League of Paragons ...
- webpack配置非CMD规范的模块
一.前言 webpack在配置多页面开发的时候 ,发现用 import 导入 Zepto 时,会报 Uncaught TypeError: Cannot read property 'createEl ...
- excel写入操作
字典列表类型数据写入excel. #导入xlwt库 import xlwt import os # 步骤1:获取excel文件的绝对路径 dirPath = os.path.join(os.getcw ...
- 手把手教你从零开始搭建SpringBoot后端项目框架
原料 新鲜的IntelliJ IDEA.一双手.以及电脑一台. 搭建框架 新建项目 打开IDE,点击File -> New Project.在左侧的列表中的选择Maven项目,点击Next. 填 ...
- 1.4 The usage of plug-in
Once upon a time, we once thought naively that Android plug-in was intended to add new features or a ...