副本集(Replica Set)拓扑结构
基本要求
副本集中包含多个成员(mongod),尽可能让成员数量为基数个,而不是偶数。奇数数量节点更容易在选举新的Primary节点时,快速决策,且不产生BUG。
副本集中的节点可能有以下类型:
Primary节点
在一个副本集中必须有只有一个节点为Primary节点,Primary节点可以进行全部的读写操作,如果一个Primary节点出现宕机,会触发其他节点进行选举,产生新的Primary节点。
Secondary节点
在一个副本集中可以有多个Secondary节点,Secondary节点通过oplog的同步机制,从Primary节点处同步数据。对于客户端或其他链接MongoDB的应用而言,Secondary节点是 只读的 ,不可写。Secondary节点通过设置vote/priority/historical等属性,可以获得不同的特殊作用。
Arbiter节点(仲裁者)
出于成本的考虑,可以选择用Arbiter节点替代Secondary节点,Arbiter节点只在选举(eletion)中起作用,并不保存任何数据。1个副本集的Arbiter数量可以多于1个,但多出来的Arbiter并没有实际的意义,因此请确认副本集中只有1个Arbiter。
数据同步
副本集可以有两种数据同步方式:
初始化时自动同步
将Secondary节点的dbpath路径下的文件全部删除,在副本集初始化(rs.initiate)或者Secondary节点重新启动时,数据都会自动同步到Secondary节点。
注:如果文件存在,可能会存在着不完全同步的不确定性结果,也有可能造成安全认证不能通过。
通过备份文件同步
待补充,不推荐_
副本集的安全认证方式
不设置安全认证
不设置安全认证,即将security.authorization设置为false(默认值就是false)。这时的副本集建立过程不受任何限制,但是存在安全性风险,可用于内网环境。
通过keyfile设置安全认证
MongoDB支持副本集节点之间通过设置一个秘钥文件来进行安全认证,具有相同keyfile的节点可以直接进行连接。
keyfile生成
可以利用openssl生成keyfile,MongoDB要求keyfile的位数为6位至1024位之间,下面是一个生成1024位秘钥的例子。
openssl rand -base64 756 > <path-to-keyfile>
chmod 400 <path-to-keyfile>
注:设置keyfile权限为400是必须的,即文件只有MongoDB的用户可访问。_
keyfile设置
在mongod.conf中配置keyfile,注意设置了keyfile即代表着security.authorization = true
。
keyfile的配置方法如下:
security:
keyFile: <path-to-keyfile>
replication:
replSetName: <replicaSetName>
net:
bindIp: localhost,<ip address>
建议:在设置keyFile之前先在Primary节点完成安全配置
副本集的建立方式
创建3个数据节点的副本集
1. 准备工作
假设我们将副本集命名为:devset-001。并且我们有3个节点,均为数据节点,对应的节点顺序和域名如下:
节点序号 | hostname | 期望类型 |
---|---|---|
0 | db-member-0 | Primary |
1 | db-member-1 | Secondary |
2 | db-member-2 | Secondary |
有可能Primary节点上已经具有我们已有的数据,如果可以,请将2个Secondary节点上的数据文件全部删除,可以先做好备份。
如果需要安全认证,请参照keyfile设置的方法准备好keyfile,并确保每个节点都具有相同的keyfile。
2. 配置并启动每个节点
在每个节点中进行如下配置,并启动mongod服务:
replication:
replSetName: "devset-001"
net:
bindIp: localhost,<ip address>
3. 配置并启动每个节点
连接Primary节点,并通过rs.initiate
函数初始化副本集:
rs.initiate( {
_id : "devset-001",
members: [
{ _id: 0, host: "db-member-0:27017" },
{ _id: 1, host: "db-member-1:27017", priority: 1 },
{ _id: 2, host: "db-member-2:27017", priority: 0.5 }
]
})
如果使用了非默认27017端口,请修改对应的端口号。priority决定了选举为Primary节点的优先级,默认为1。
4. 确认配置成功
可以通过rs.conf()
函数来检查配置是否与预期相同,也可以通过rs.status()
来了解各个节点状态。
5. 修改配置
以下函数可以完成配置修改:
rs.reconfig()
可以完成全部配置修改操作,对rs.conf()
返回结果保存到conf变量,修改后直接调用re.reconfig(conf)
即可;rs.add()
可以添加节点rs.addArb()
可以添加仲裁节点rs.remove()
可以删除节点
创建带有Arbiter的副本集
要使一个副本集具有Arbiter节点,可以采用以下两种方式:
1. 初始化副本集时即配置Arbiter
rs.initiate( {
_id : "devset-001",
members: [
{ _id: 0, host: "db-member-0:27017" },
{ _id: 1, host: "db-member-1:27017", priority: 1 },
{ _id: 2, host: "db-member-2:27017", arbiterOnly: true }
]
})
注:设置arbiterOnly=true
时,节点的priority将被设定为0。
2. 通过rs.addArb()
方法向副本集中加入Arbiter
rs.addArb("db-member-2:27017");