Mongodb 副本集

1.介绍

Mongodb官方提供了一个复制功能,它提供冗余的功能,它可以将数据保存在不同服务器上,并保持多个服务器的数据一致性。

当主要提供数据的服务器出现了问题不能访问等问题,副本集中的其他服务器会自动替代主要提供数据的服务器进行提供数据功能。

副本集中有三个角色:

  1. 主节点:所有副节点的数据均来自于主节点,并且只能对主节点进行读写操作。
  2. 副节点:数据来自于主节点,可以进行读取操作,但是不能进行写操作。
  3. 仲裁者:不含数据也不与客户端交流,只在选举主节点的时候进行投票。

2.选举机制

Mongodb最多支持50个副本集成员以及最多7个选举成员,启动副本集后将开始第一次选举,在选举过程中,所有副本集成员都只能读取,直到选举出主节点后主节点才能进行读写,但是在这个期间副本成员可以提供查询服务。

而主节点要保持主节点的位置需要每两秒发送一个ping请求,如果10秒内没有得到响应则标记为不可访问,当一半以上的副本集成员不可访问,那么主节点将降级为副节点。

其中设置成员的priority值可以优先成员主节点,这个值介于0-1000之间,默认为1,如果这个值为0,那么它的votes值也为0,只要votes为0的成员不能投选举票,但是可以投否决票。但是我们也可以手动设置成员priority值为大于1的成员是否有投票权利

在进行选举的时候,其他成员会作以下几点判断来进行投票参与选举的成员是否能作为主节点,选举步骤:

  1. 自己是否能与主节点通讯。
  2. 参与选举的成员是否比其他参与选举的成员数据最新。
  3. 如果参与选举的成员数据相等则尝试使用具有最高priority的值的成员。

3.仲裁者

仲裁者的出现是为了避免只有两个成员的副本集,两个成员的副本集投票可能无法满足一半以上的投票情况。

仲裁者不负责数据和客户端交流,只有参与选举的功能,需要注意的是仲裁者一旦设置过后就再也无法变为非仲裁者了。

4.部署副本集

首先部署一个副本集很简单,下面的代码是部署了一个本地含有三个成员的副本集。

建立三个成员的副本集,首先你得建立三个数据库的存放目录:

mkdir -p ./replDb/s0 ./replDb/s1 ./replDb/s2

然后我们启动三个副本集成员,其中replSet参数后面跟的是副本集的名称,将需要有关联的成员的副本集名称要一致。

mongod --dbpath ./replDb/s0 --port 27017 --replSet s0

mongod --dbpath ./replDb/s0 --port 27018 --replSet s0

mongod --dbpath ./replDb/s0 --port 27019 --replSet s0

创建仲裁者也同样非常简单,建立一个空的数据目录,然后和其他副本集成员一样设置同样的副本集名称启动,最后通过rs.add方法的第二个参数设置为true

mongod --dbpath ./replDb/s5 --port 27020 --replSet s0

mongod --port 27017 --host localhost

> rs.add('localhost:27020', true);

然后通过Mongo Shell进入到端口为27017的成员中,并配置副本集。

mongod --port 27017 --host localhost

进入到Mongo Shell后通过rs.initiate方法来配置副本集。

> var conf = {
    _id: 'r0',
    version: 1,
    members: [
        {
            _id: 0,
            host: 'localhost:27017'
        },
        {
            _id: 1,
            host: 'localhost:27018'
        },
        {
            _id: 2,
            host: 'localhost:27019'
        },
        {
            _id: 3,
            host: 'localhost:27020'
        }
    ]
};

> rs.initiate(conf);

initiate接受一个对象,对象_id为副本集名称,必须和启动副本集设置的一致才能添加进来(本例为rs0)。version为版本号,每当我们修改副本集配置的时候这个版本号都会递加1,而members则为副本集成员,我们可以在这里一次性添加完,也可以只添加一个后面再通过add方法添加,比如下面这样:

> rs.add('localhost:27018');
> rs.add('localhost:27019');

5.删除副本集

删除副本集通过rs.remove方法来删除,它接受一个<localhost>:<port>这样的字符串。下面是删除一个副本集成员:

> rs.remove('localhost:27019');

6.查询副本集配置

查看副本集配置是通过rs.conf方法查询,返回包含所有副本集的配置内容.

> rs.conf();

7.查询主节点

每当使用rs.add方法添加成员的时候可能会影响选举来选择主节点是谁,查看主节点通过rs.isMaster()方法来查看。

> rs.isMaster();

返回的内容中有几个可以了解

{
    "hosts" : [  //副本集成员
        "localhost:27017",
        "localhost:27018",
        "localhost:27019"
    ],
    "setName" : "rs0", //副本集名称
    "setVersion" : 3, //副本集配置版本
    "ismaster" : true, //是否是主节点
    "primary" : "localhost:27017",  //主节点成员的主机地址
    "me" : "localhost:27017",   //当前所在主机
}

8.读取副节点

副节点默认是无法读取的,我们可以通过rs.setSlaveOk()方法来设置Slave属性为true。下面是设置端口为27018的副节点可以进行读取

mongod --port 27018 --host localhost

> rs.setSlaveOk();

9.隐藏成员

隐藏成员通过设置成员的hidden属性为true并且优先值priority为0则可以隐藏此成员,隐藏成员不能当主节点也不能当其他成员的复制源

> rs.add({
>   _id: 1,
>   _host: 'localhost:27017',
>   hidden: true,
>   priority: 0
> })

10.延迟复制

通过设置成员的slaveDelay的值并且优先值priority为0,来让当前成员滞后多少秒后才开始复制数据。

> rs.add({
>   _id: 1,
>   _host: 'localhost:27017',
>   slaveDelay: 120,
>   priority: 0
> })

11.索引管理

通过成员的buildIndexes的值并且优先值priority为0,来设置是否在备份机器上建立相同的索引,一般这个选项只用于纯粹备份的服务器。

下面的代码设置添加的副本集成员不创建索引。

> rs.add({
>   _id: 1,
>   _host: 'localhost:27017',
>   buildIndexes: false
>   priority: 0
> })

12.参考

MongoDB权威指南(第2版)

Mongodb Docs

文档信息