[MongoDB学习笔记二]MongoDB副本集

1. 副本集的特性

  1)一台主服务器(Primary),多台从服务器(Secondary)

  2)Primary挂了之后,从服务器自动完成从它们之中选举一台服务器作为主服务器,继续工作,这就解决了单点故障,因此,在这种情况下,MongoDB集群能够继续工作

  3)挂了的主服务器恢复到集群中只能以Secondary服务器的角色加入进来

2. 副本集环境搭建

 2.1副本集闭环配置(以三台机器配置为例)

port=27017
bind_ip=127.0.0.1
dbpath=/home/tom/development/mongoDBdata/replicaA
replSet=child/127.0.0.1:27018
port=27018
bind_ip=127.0.0.1
dbpath=/home/tom/development/mongoDBdata/replicaB
replSet=child/127.0.0.1:27019
port=27019
bind_ip=127.0.0.1
dbpath=/home/tom/development/mongoDBdata/replicaC
replSet=child/127.0.0.1:27017

 2.2 查看副本集状态

rs.status()

2.3 启动三台服务器

在~/development/mongoDBConfig目录建立三个配置文件A.conf,B.conf和C.conf,内容分别是上面闭环设置的3台机器的配置,如A.conf的内容是

port=27017
bind_ip=127.0.0.1
dbpath=/home/tom/development/mongoDBdata/replicaA
replSet=child/127.0.0.1:27018

在~/devlopment/mongDBConfig目录下,运行命令启动三台服务器

mongd --config A.conf
mongd --config B.conf
mongd --config C.conf

此时三台服务器都在输出如下类似的日志,不断尝试跟指定的conf文件中指定的child host进行通信(contact),例如27017的

Wed Aug  6 07:26:19.088 [rsStart] trying to contact 127.0.0.1:27018
Wed Aug  6 07:26:19.089 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:26:29.089 [rsStart] trying to contact 127.0.0.1:27018
Wed Aug  6 07:26:29.090 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:26:39.090 [rsStart] trying to contact 127.0.0.1:27018
Wed Aug  6 07:26:39.091 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:26:49.091 [rsStart] trying to contact 127.0.0.1:27018
Wed Aug  6 07:26:49.092 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:26:59.092 [rsStart] trying to contact 127.0.0.1:27018
Wed Aug  6 07:26:59.094 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:27:38.614 [rsStart] trying to contact 127.0.0.1:27019
Wed Aug  6 07:27:38.615 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:27:48.615 [rsStart] trying to contact 127.0.0.1:27019
Wed Aug  6 07:27:48.616 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:27:58.616 [rsStart] trying to contact 127.0.0.1:27019
Wed Aug  6 07:27:58.617 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:28:08.617 [rsStart] trying to contact 127.0.0.1:27019
Wed Aug  6 07:28:08.618 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:28:18.618 [rsStart] trying to contact 127.0.0.1:27019
Wed Aug  6 07:28:18.619 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:28:35.770 [rsStart] trying to contact 127.0.0.1:27017
Wed Aug  6 07:28:35.770 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:28:45.771 [rsStart] trying to contact 127.0.0.1:27017
Wed Aug  6 07:28:45.772 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:28:55.772 [rsStart] trying to contact 127.0.0.1:27017
Wed Aug  6 07:28:55.773 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Wed Aug  6 07:29:05.773 [rsStart] trying to contact 127.0.0.1:27017
Wed Aug  6 07:29:05.774 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)

 2.4 副本集环境初始化

上面的日志表明副本集还没有进行初始化,使用如下命令在任意一台服务器的Javascript Shell上运行,完成副本集初始化

use admin
db.runCommand({"replSetInitiate": {
    "_id": "child",
    "members": [
        {
            "_id": 1,
            "host": "127.0.0.1:27017"
        },
        {
            "_id": 2,
            "host": "127.0.0.1:27018"
        },
        {
            "_id": 3,
            "host": "127.0.0.1:27019"
        }
    ]
}
});

 此时查看副本集的服务器日志输出,没台机器有如下的日志输出,表明闭环建立成功

Wed Aug  6 07:45:45.954 [initandlisten] connection accepted from 127.0.0.1:46181 #8 (3 connections now open)

 rs.status()察看副本集状态,得到如下的输出,可见27017是Primary服务器,其它的是Secodary服务器

child:PRIMARY> rs.status();
{
	"set" : "child",
	"date" : ISODate("2014-08-05T23:56:21Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 1,
			"name" : "127.0.0.1:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 2338,
			"optime" : Timestamp(1407282254, 1),
			"optimeDate" : ISODate("2014-08-05T23:44:14Z"),
			"self" : true
		},
		{
			"_id" : 2,
			"name" : "127.0.0.1:27018",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 722,
			"optime" : Timestamp(1407282254, 1),
			"optimeDate" : ISODate("2014-08-05T23:44:14Z"),
			"lastHeartbeat" : ISODate("2014-08-05T23:56:19Z"),
			"lastHeartbeatRecv" : ISODate("2014-08-05T23:56:20Z"),
			"pingMs" : 0,
			"syncingTo" : "127.0.0.1:27017"
		},
		{
			"_id" : 3,
			"name" : "127.0.0.1:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 720,
			"optime" : Timestamp(1407282254, 1),
			"optimeDate" : ISODate("2014-08-05T23:44:14Z"),
			"lastHeartbeat" : ISODate("2014-08-05T23:56:19Z"),
			"lastHeartbeatRecv" : ISODate("2014-08-05T23:56:20Z"),
			"pingMs" : 0,
			"syncingTo" : "127.0.0.1:27017"
		}
	],
	"ok" : 1
}

2.5 验证

2.5.1.在主服务器27017上执行如下命令:

use foolbar
db.persons.insert({"name":"tom"});
db.persons.find();
>>>{ "_id" : ObjectId("53e1709f07c1625ed566a67f"), "name" : "tom" }

 上面创建了一个数据库foolbar,一个集合persons,插入一条文档,然后执行查询

2.5.2.在从服务器27018上执行查询

use foolbar
db.persons.find()
>>>error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

 查询错误,提示27018是Secondary服务器,但是SlaveOk是false,不能做查询操作,所以需要设置从服务器,使之能够支持数据读取操作

2.5.3.关掉主服务器27017

那么MongoDB从27018和27019上自动选举一台作为主服务器,此时如果重启27017,那么27017将作为Secondary服务器加入到集群中。假如27019被选举为Primary,那么对27019做针对foolbar数据库persons集合的查询,会查询来1中创建的数据

2.5.4.设置读写分离

无论是主从复制还是副本集复制,一方面提供数据的备份,另外一点通过读写分离提高读写性能,在副本集复制方式下,默认情况下,从服务器只进行数据的同步,但是不提供数据读取功能,要想使从服务器提供数据读取功能,需要设置从服务器的slaveOkay为true,但是遗憾的是,如此重要的设置,MongoDB的Javascript Shell竟然没有提供修改的API,难道副本集的本意只做数据同步备份,不做读写分离?It doesn't make any sense!!!要修改slaveOkay,只能通过MongoDB的语言客户端如Java进行修改,这在以后再讲。

猜你喜欢

转载自bit1129.iteye.com/blog/2100773