MongoDB(五)副本集

副本集由一组服务器组成,或者说由一组节点组成,其中有一个是主节点(primary),可以处理客服端的读写请求;
还有多个备份节点(secondary),用于保存主节点的数据副本。
如果主节点挂了,备份节点会自动将其中一个成员升级为新的主节点,当然是由“大多数原则”来选举主机点的,
由一半以上的节点支持的节点升级为新的主节点。

下面看创建副本集的过程。
/home/mongodb-3.2.8-replSet-1/bin/mongod --replSet spock --dbpath /home/mongodb-3.2.8-replSet-1/data/db --port 20000 --fork
 --pidfilepath /home/mongodb-3.2.8-replSet-1/mongodb.pid --logpath /home/mongodb-3.2.8-replSet-1/logs/mongod.log --logappend --logRotate rename

/home/mongodb-3.2.8-replSet-2/bin/mongod --replSet spock --dbpath /home/mongodb-3.2.8-replSet-2/data/db --port 20001 --fork
 --pidfilepath /home/mongodb-3.2.8-replSet-2/mongodb.pid --logpath /home/mongodb-3.2.8-replSet-2/logs/mongod.log --logappend --logRotate rename

/home/mongodb-3.2.8-replSet-3/bin/mongod --replSet spock --dbpath /home/mongodb-3.2.8-replSet-3/data/db --port 20002 --fork
 --pidfilepath /home/mongodb-3.2.8-replSet-3/mongodb.pid --logpath /home/mongodb-3.2.8-replSet-3/logs/mongod.log --logappend --logRotate rename
其中,
--replSet spock,指明建立以"spock"为标识名称的副本集,所有节点都要指定相同的副本集标识名称
当然,我是以单台机启动三个MongoDB实例来说明副本集创建的。

> db = (new Mongo("192.168.20.111:20000")).getDB("test");
test

编辑副本集的节点列表配置
> config = {
...  "_id":"spock",
...  "members":[
...  {"_id":0,"host":"192.168.20.111:20000"},
...  {"_id":1,"host":"192.168.20.111:20001"},
...  {"_id":2,"host":"192.168.20.111:20002"}
...  ]
... };
{
    "_id" : "spock",
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.20.111:20000"
        },
        {
            "_id" : 1,
            "host" : "192.168.20.111:20001"
        },
        {
            "_id" : 2,
            "host" : "192.168.20.111:20002"
        }
    ]
}

# rs 是个全局变量,包含相关的辅助函数

#配置副本集
> rs.initiate(config);
{ "ok" : 1 }

#rs.config()查看副本集是否配置成功
spock:OTHER> rs.config();
{
    "_id" : "spock",
    "version" : 1,
    "protocolVersion" : NumberLong(1),
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.20.111:20000",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
                
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        },
        {
            "_id" : 1,
            "host" : "192.168.20.111:20001",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
                
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        },
        {
            "_id" : 2,
            "host" : "192.168.20.111:20002",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
                
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        }
    ],
    "settings" : {
        "chainingAllowed" : true,
        "heartbeatIntervalMillis" : 2000,
        "heartbeatTimeoutSecs" : 10,
        "electionTimeoutMillis" : 10000,
        "getLastErrorModes" : {
            
        },
        "getLastErrorDefaults" : {
            "w" : 1,
            "wtimeout" : 0
        },
        "replicaSetId" : ObjectId("58394e5480416fb93ba62bc8")
    }
}


在上面的结果中,其中
{
...
"members" : [
        {
        ...
        "priority" : 1
        }
        ..
        ]
}

"priority" : 1,表示了节点的优先级,用来表示节点成为主节点的程序,默认是1,如果设置为0则表示永远不可能成为主节点


#修改副本集配置

#添加副本集成员
> rs.add("192.168.20.111:20003");

#删除副本集成员
> rs.remove("192.168.20.111:20003");

编辑完副本集配置,主节点会退化为普通的备份节点,以接受新的配置,然后会恢复正常。

如需要重要编辑配置,需要调用以下辅助函数将新的配置发送给服务器:

#config就是配置了
> rs.reconfig(config);

查看副本集的状态

> rs.isMaster();
{
    "hosts" : [
        "192.168.20.111:20000",
        "192.168.20.111:20001",
        "192.168.20.111:20002"
    ],
    "setName" : "spock",
    "setVersion" : 1,
    "ismaster" : true,
    "secondary" : false,
    "primary" : "192.168.20.111:20000",
    "me" : "192.168.20.111:20000",
    "electionId" : ObjectId("7fffffff0000000000000001"),
    "maxBsonObjectSize" : 16777216,
    "maxMessageSizeBytes" : 48000000,
    "maxWriteBatchSize" : 1000,
    "localTime" : ISODate("2016-11-26T09:16:05.880Z"),
    "maxWireVersion" : 4,
    "minWireVersion" : 0,
    "ok" : 1
}

其中,从上面返回结果中,
"me" : "192.168.20.111:20000" ==>> 看出当前节点
"ismaster" : true ==>> 当前节点是否主节点
"secondary" : true  ==>> 当前节点是否备份节点
"primary" : "192.168.20.111:20000" ==>> 看出主节占的信息


选举主节点,主节点只有得到大多数节点的支持时才能作为主节点,这里的大多数,指副本集中的节点列表中有半数以上,
比如3个节点,需要至少有2个节点支持;5个节点,则至少有3个节点支持才能作为主节点。

主节点插入数据
spock:PRIMARY> db.foo.insert({"name":"lin"});
WriteResult({ "nInserted" : 1 })

备份节点是不能插入数据的
spock:SECONDARY> db.foo.insert({"name":"abc"});
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })

备份节点可能落后于主节点,没有最新写入的数据,所以备份节点在默认情况下是拒绝读取操作的,这样可以防止应用程序取得过期的数据。
所以这时,查询备份节点,会有错误提示
spock:SECONDARY> db.foo.find();
Error: error: { "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 }

如果需要从备份节点读取数据,需要设置“从备份节点读取数据没问题”的标识
spock:SECONDARY> rs.slaveOk();
spock:SECONDARY> db.foo.find();
{ "_id" : ObjectId("58395833a53d33c854e33450"), "name" : "lin" }

..
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值