Skip to the content.

副本集(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. 修改配置

以下函数可以完成配置修改:

创建带有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");