共计 6796 个字符,预计需要花费 17 分钟才能阅读完成。
副本集(Replica Set)是一组 MongoDB 实例组成的集群,由一个主(Primary)服务器和多个备份(Secondary)服务器构成。通过 Replication,将数据的更新由 Primary 推送到其他实例上,在一定的延迟之后,每个 MongoDB 实例维护相同的数据集副本。通过维护冗余的数据库副本,能够实现数据的异地备份,读写分离和自动故障转移。
一,MongoDB 版本和环境
在 Windows 上创建包含三个节点的副本集,使用的环境:
- 数据库:MongoDB 版本 3.2.9
- Server 环境:Windows Server 2012 R2
- 可视化编程环境:Robomongo 版本 0.08.4
- 三台 Windows Server:srv1,srv2,srv3
二,拓扑结构分析
创建一个 Replica Set,包含三个成员:一个 Primary 成员和两个 Secondary 成员,Primary 用于处理客户端请求,Secondary 用于保存 Primary 的数据副本。客户端 Application 在 Primary 节点上进行读写操作,通过 Replication 的异步同步机制,将数据操作同步到 Secondary 成员,在一定的延迟之后,三个成员拥有相同的数据集。
理论上,每个成员可以分布在不同的数据中心机房内,这些数据中心可能相距甚远,实现数据的异地备份;可以设置 Primary 节点只负责写入操作,而使 Secondary 节点负责读取操作,实现数据集的读写分离;如果 Primary 连接中断超过 10s,其他节点会自动选举出一个 Primary 节点,负责响应客户端 Application 的请求,实现数据的自动故障转移。
三,技术原理说明
1,以 Replica Set 模式启动 MongoDB 实例
MongoDB Instance 有两种不同的启动方式:单机模式(Standalone)和副本集模式(Replica Set),在启动 mongod 时,如果设置 replSet 参数,那么 MongoDB 实例以副本集模式启动;如果不设置 replSet 参数,那么 MongoDB 以单机模式启动。
单机实例是指运行在服务器上的一个 mongod 进程,该进程不是任何一个 Replica Set 的成员,因此,单机实例不能自动故障转移,在产品环境中,风险很高,如果服务器崩溃了,客户端 App 至少在一段时间内不可访问,如果硬件出现问题,可能会造成数据的永久丢失。建议,使用 Replica Set,至少保留两份数据集副本。
2,选举 Primary 成员
在 Replica Set 中有两种成员:Primary 成员和 Secondary 成员,一个 Replica Set 只能有一个 Primary 成员,但可以有多个 Secondary 成员。Primary 用于处理客户端请求,Secondary 用于保存 Primary 的数据副本。如果 Primary 崩溃了,Replica Set 探测到 Primary 不可访问,将启动自动故障转移进程,从剩下的 Secondary 成员中,投票选举出一个成员作为 Primary,接收和处理客户端的请求。
选举 Primary 成员时,使用“大多数 ”和“ 一票否决”原则。在 Replica Set 中,每个成员只能要求自己被选举为 Primary 节点。当一个 Secondary 成员无法与 Primary 成员连通时,该成员就会发起选举,请求其他成员将自己选举为 Primary 成员,只有得到“大多数”成员的支持,该成员才能被选举为 Primary 成员;只要有一个成员否决,选举就会取消。
不是每一个成员都有投票选举的权利,在一个 Replica Set 中,最多有 7 个成员用于投票选举的权利,Primary 成员是由这 7 个成员选举出来的。有投票权利的成员,其属性:”votes” 是 1;若为 0,表示该成员没有投票权利。
3,操作日志
MongoDB 使用操作日志(oplog)来实现复制(Replication)功能,oplog 包含了 Primary 成员的每一个更新操作,通过将 oplog 传递到其他 Secondary 成员中,在其他成员中重做(redo)已经提交的操作,实现数据的异步同步。Replica Set 中的每个成员都维护着自己的 oplog,记录着每一个从 Primary 成员复制操作的数据。复制操作的过程是先复制数据,再将操作写入到 oplog 中。如果某一个成员在执行操作时失败,当该成员重启之后,自动从 oplog 中最后一个操作进行同步。由于复制操作的过程是先复制数据,再写入 oplog,该成员可能会在已经同步的数据上再次执行复制操作,MongoDB 在设计 oplog 时,就考虑到这种情况:将 oplog 中的同一个操作执行多次,与执行一次的结果是一样的。
oplog 保存的是对每个 doc 的更新操作日志,如果一个命令只更新一个 doc,那么 Replication 进程向 oplog 插入一条日志;如果一个命令更新多个 doc,那么 Replication 进程向 oplog 插入多条日志,每一条日志只更新一个 doc。
oplog 的大小是固定的,只能保存特定数量的操作日志,如果 Primary 成员更新的数据量特别大,oplog 很快就被填满,Secondary 来不及同步数据,Primary 成员就将 oplog 中的日志,这样,Secondary 成员就会变成陈旧的(Stale)。建议,让 Primary 成员使用比较大的 oplog,保存足够多的操作日志。
四,创建配置文档
1,创建 mongod 启动的配置文件
在每台 server 上创建配置文件,将配置文件存放在目录 C:\data\ 中。在同一个 Replica Set 中的所有成员必须有相同的 Replica Set Name,这里设置为“rs0”。
--srv1 config_file_name:rs0_1.conf
dbpath=C:\data\db\db_rs0
logpath=C:\data\db\db_rs0\rs0_1.log
port=40001
replSet=rs0
--srv2 config_file_name:rs0_2.conf
dbpath=C:\data\db\db_rs0
logpath=C:\data\db\db_rs0\rs0_2.log
port=40002
replSet=rs0
--srv3 config_file_name:rs0_3.conf
dbpath=C:\data\db\db_rs0
logpath=C:\data\db\db_rs0\rs0_3.log
port=40003
replSet=rs0
配置参数含义:
- replSet:设置 Replica Set 的 name,在各个配置文件中,其值必须相同。
- dbpath:MongoDB 用于存储数据的目录,默认值是 C:\data\db
- logpath:用于记录 mongod 的日志数据
- port:指定 MongoDB 监听的端口,默认值是 27017
2,以配置文件方式启动 mongod
一般情况下,mongod 的参数值是不变的,将这些参数写入到配置文件中,能够简化 MongoDB 的管理。
mongod 命令有参数:–config 或 -f,用于引用配置文件。
--srv1
mongod -f C:\data\rs0_1.conf
--srv2
mongod -f C:\data\rs0_2.conf
--srv3
mongod -f C:\data\rs0_3.conf
3,启动 mongo shell
在任意一台 Server 上打开三个 mongo shell,使用参数 –host 指定 Server Name,使用 –port 指定端口号。由于 mongod 没有使用默认的监听端口 27017,因此,必须使用 在 mongo shell 中使用 –port 参数显式指定监听的 Port。
--connect srv1
mongo --host srv1 --port 40001
--connect srv2
mongo --host srv2 --port 40002
--connect srv3
mongo --host srv3 --port 40003
五,配置 Replica Set
在不同的 Server 上运行不同的 MongoDB Instance,但是,每个 mongod 都不知道其他 mongod 的存在,为了让每个 mongod 能够感知彼此的存在,需要配置 Replica set,增加成员。
1,使用配置文档为 Replica Set 增加成员
在 srv1 的 mongo shell 中,创建配置文档,调用 rs.initiate()函数,按照配置文档来初始化 Replica Set。
conf=
{"_id" : "rs0",
"members" : [{ "_id" : 0, "host" : "srv1:40001" },
{"_id" : 1, "host" : "srv2:40002" },
{"_id" : 2, "host" : "srv3:40003" }
]
}
rs.initiate(conf)
在配置 doc 中,使用 ”_id” : “rs0” 指定 Replica Set 的 name,members 数组指定 Replica Set 的成员的 ID 和 host(“host:port”)。等到所有成员配置完成之后,Replica Set 会自动选举出一个 Primary 节点,两个 Secondary 节点。在 Primary 节点上进行更新操作,就能同步到 Secondary 节点了。
2,修改 Replica Set
如果以 rs.initiate()方式初始化 Replica Set,那么 MongoDB 以默认配置文档初始化 Replica Set,可以通过 add()函数增加成员。
2.1 向 Replica Set 中增加一个成员
rs.add("host:port")
2.2 从 Replica Set 中删除一个成员
rs.remove("host")
2.3 查看 Replica Set 的配置
rs.conf()
2.4 重新配置 Replica Set
var conf=rs.conf()
conf.members[1].priority =5
--at primary member
rs.reconf(conf)
--at secondary member
rs.reconf(conf,{force:true})
2.5 查看 Replica Set 的状态
rs.status()
六,维护 Replica Set
1,查看 Replica Set 的配置信息
rs.conf()
配置文档主要分为三块:Replica Set 的 ID 和 Version,Members 数组 和 Settings,下面是经过简化的配置信息。
{"_id" : "rs0",
"version" : 202997,
"members" : [
{"_id" : 1,
"host" : "srv1:40001",
"arbiterOnly" : false,
"hidden" : false,
"priority" : 5,
"votes" : 1
}, {...}
],
"settings" : {.....}
}
Replica Set 的 ID 字段唯一标识一个 Replica Set,每一个 Replica Set 都有一个自增的版本号,由 Version 字段标识,标识 Replica Set 的不同版本。version 字段的初始值是 1,每次修改 Replica Set 的配置时,version 字段都会自增。
Settings 字段的值是应用到 Replica Set 中所有成员的配置信息。
最关键的是 members 数组的字段,标识每个成员的配置信息。
- arbiterOnly:0 或 1,标识一个仲裁(arbiter),Arbiter 的唯一作用是参与 Primary 的选举,Arbiter 不保存数据,不会为 client 提供服务,它存在的意义就是为了选举 Primary。
- hidden:0 或 1,表示该成员是不是隐藏成员,Hidden 成员的主要作用是备份数据,可以使用性能较差的服务器作为 Hidden 成员。Hidden 成员不会接收 Client 的请求,也不会成为 Primary。在设置 Hidden 成员时,必须设置 members[n].priorty 属性为 0;
- priority:数值类型,用于设置成员成为 Primary 的优先级。priority 越高的成员,越有机会成为 Primary。如果 priority=0,那么该成员永远不会成为 Primary。
- votes:1 或 0,表示该成员的投票的数量,在每个 Replica Set 中,最多有 7 个成员,其 votes 属性值是 1。votes 属性是 1 的成员(voting members)拥有选举 Primary 的权利。一个成员要想成为一个 Primary,那么必须获得 voting members 的大多成员的支持。
在 Replica Set 中,如果 voting members 的数量是 5,那么一个成员成为 Primary 的条件是:获得超过 2 个 voting members 的支持,并且没有任何 voting members 反对。只要有任意一个 voting member 反对该成员成为 Primary,那么该成员就不能成为 Primary。
2,强制一个成员成为 Primary
如果将一个成员的 priority 属性在 Replica Set 的所有成员中是最高的,那么该成员最有可能成为 Primary。
将成员 0 的 priority 设置 5,其他成员的 priority 设置为 1,这样,成员 0 成为 Primary 的优先级是最高的。
cfg = rs.conf()
cfg.members[0].priority = 5
cfg.members[1].priority = 1
cfg.members[2].priority = 1
rs.reconfig(cfg)
七,测试数据
1,在 Primary 上读写数据
db.users.insert({_id:1,name:"a",age:24})
2,在 Secondary 上读取数据
默认情况下,客户端不能从 Secondary 成员中读取数据。在 Secondary 成员上显式执行 setSlaveOk 之后,才能从 Secondary 节点读取数据。
rs.setSalveOk()
db.users.find({_id:1})
八,查看 mongod 服务器的命令行参数
db.serverCmdLineOpts()
/* 0 */
{"argv" : [
"mongod",
"-f",
"C:\\data\\rs0_1.conf"
],
"parsed" : {
"config" : "C:\\data\\rs0_1.conf",
"net" : {"port" : 40001},
"replication" : {"replSet" : "rs0"},
"storage" : {"dbPath" : "C:\\data\\db\\db_rs0"},
"systemLog" : {
"destination" : "file",
"path" : "C:\\data\\db\\db_rs0\\rs0_1.log"
}
},
"ok" : 1
}
更多 MongoDB 相关教程见以下内容:
CentOS 编译安装 MongoDB 与 mongoDB 的 php 扩展 http://www.linuxidc.com/Linux/2012-02/53833.htm
CentOS 6 使用 yum 安装 MongoDB 及服务器端配置 http://www.linuxidc.com/Linux/2012-08/68196.htm
Ubuntu 13.04 下安装 MongoDB2.4.3 http://www.linuxidc.com/Linux/2013-05/84227.htm
MongoDB 入门必读(概念与实战并重) http://www.linuxidc.com/Linux/2013-07/87105.htm
Ubunu 14.04 下 MongoDB 的安装指南 http://www.linuxidc.com/Linux/2014-08/105364.htm
《MongoDB 权威指南》(MongoDB: The Definitive Guide)英文文字版[PDF] http://www.linuxidc.com/Linux/2012-07/66735.htm
Nagios 监控 MongoDB 分片集群服务实战 http://www.linuxidc.com/Linux/2014-10/107826.htm
基于 CentOS 6.5 操作系统搭建 MongoDB 服务 http://www.linuxidc.com/Linux/2014-11/108900.htm
MongoDB 的详细介绍:请点这里
MongoDB 的下载地址:请点这里
参考 doc:
Replication
Replica Set Tutorials
MongoDB – Replication
Replica Set Configuration
Force a Member to Become Primary
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-09/135646.htm