ongoDB 基础(七)复制

mongodb中的复制可以在多台服务器中同步数据。

复制提供了冗余和增加了数据的高可用性,防止单个节点易丢失数据的可能性,也可以用来进行读写分离提高客户端操作性能。


复制集中各节点的mongodb实例有相同的数据集副本。主节点可以接收客户端所有写操作记录到日志中,从库复制主库的操作日志记录应用到其数据库中。

一个客户端只能有一个主节点,如果主节点不可用(10秒内无法连接),复制集中将选一个成员节点作为主节点。



mongodb复制的基本结构如下:

技术分享




前期 — 配置服务器名称和IP绑定:


1.  设置服务器名称,3台服务器各自设置自己的主机名(当前终端需重新打开才变化)

[root@mongodb11 ~]# vi/etc/sysconfig/network

HOSTNAME= mongodb11.kk.net

2. 不重启计算机则执行以下方法:

[root@mongodb11 ~]# hostname mongodb11.kk.net


#另两台也更改服务器名称:

HOSTNAME= mongodb12.kk.net

HOSTNAME= mongodb13.kk.net

[root@mongodb12 ~]#hostname mongodb12.kk.net

[root@mongodb13 ~]#hostname mongodb13.kk.net


3. 在3台服务器文件hosts 中都添加以下3行:

# vi /etc/hosts

192.168.1.11    mongodb11.kk.net
192.168.1.12    mongodb12.kk.net
192.168.1.13    mongodb13.kk.net


实验 — 复制的部署测试:


给3台服务器配置mongodb启动参数(参数如下表格):

[root@mongodb ~]# vi/etc/mongod.conf

192.168.1.11(mongodb11.kk.net)#将作为主库

pidfilepath=/var/run/mongodb/mongod.pid

logpath=/var/log/mongodb/mongod.log

dbpath=/var/lib/mongo

logappend=true

bind_ip=192.168.1.11

port=27017

fork=true

replSet=rs0

192.168.1.12(mongodb12.kk.net)

pidfilepath=/var/run/mongodb/mongod.pid

logpath=/var/log/mongodb/mongod.log

dbpath=/var/lib/mongo

logappend=true

bind_ip=192.168.1.12

port=27018

fork=true

replSet=rs0

192.168.1.13(mongodb13.kk.net)

pidfilepath=/var/run/mongodb/mongod.pid

logpath=/var/log/mongodb/mongod.log

dbpath=/var/lib/mongo

logappend=true

bind_ip=192.168.1.13

port=27019

fork=true

replSet=rs0

配置完成后重启服务:(replSet=rs0  #复制集名称:rs0)

[root@mongodb ~]#service mongod restart


【在192.168.1.11(mongodb11.kk.net)中部署】

1. 登录到mongodb中:

[root@mongodb11 ~]# mongo192.168.1.11:27017


2. 初始化复制集:(集合为:"rs0" ;第一个成员为:"mongodb11.kk.net:27017" )

>rs.initiate({_id: "rs0",members: [{ _id: 0 , host: "mongodb11.kk.net:27017" }]})

技术分享


3. 添加另2个成员:

rs.add("mongodb12.kk.net:27018")
rs.add("mongodb13.kk.net:27019")

技术分享


4. 查看成员信息 (或者使用 db.isMaster()    )

rs0:PRIMARY> rs.status()
{
	"set" : "rs0",
	"date" : ISODate("2015-05-13T13:56:35.020Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "mongodb11.kk.net:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 990,
			"optime" : Timestamp(1431525353, 1),
			"optimeDate" : ISODate("2015-05-13T13:55:53Z"),
			"electionTime" : Timestamp(1431524773, 2),
			"electionDate" : ISODate("2015-05-13T13:46:13Z"),
			"configVersion" : 3,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "mongodb12.kk.net:27018",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 47,
			"optime" : Timestamp(1431525353, 1),
			"optimeDate" : ISODate("2015-05-13T13:55:53Z"),
			"lastHeartbeat" : ISODate("2015-05-13T13:56:33.382Z"),
			"lastHeartbeatRecv" : ISODate("2015-05-13T13:56:34.022Z"),
			"pingMs" : 0,
			"syncingTo" : "mongodb11.kk.net:27017",
			"configVersion" : 3
		},
		{
			"_id" : 2,
			"name" : "mongodb13.kk.net:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 41,
			"optime" : Timestamp(1431525353, 1),
			"optimeDate" : ISODate("2015-05-13T13:55:53Z"),
			"lastHeartbeat" : ISODate("2015-05-13T13:56:33.412Z"),
			"lastHeartbeatRecv" : ISODate("2015-05-13T13:56:33.467Z"),
			"pingMs" : 1,
			"configVersion" : 3
		}
	],
	"ok" : 1
}

或者使用该方法查看,结果也是一样:

use admin
db.runCommand( { replSetGetStatus : 1 } )

详细说明如下:( 参考: replSetGetStatus ) (state 参考 Replica Set Member States

"_id" :  #集群中节点编号
"name" :  #成员服务器名称及端口
"health" :  #表示成员中的健康状态(0:down;1:up)
"state" :  #为0~10,表示成员的当前状态
"stateStr" :  #描述该成员是主库(PRIMARY)还是备库(SECONDARY)
"uptime" :  #该成员在线时间(秒)
"optime" :  #成员最后一次应用日志(oplog)的信息
"optimeDate" :  #成员最后一次应用日志(oplog)的时间
"electionTime" :  #当前primary从操作日志中选举信息
"electionDate" :  #当前primary被选定为primary的日期
"configVersion" :  #mongodb版本
"self" :  #为true 表示当前节点




5. 测试操作。在主库中,可以任意操作:

rs0:PRIMARY> show dbs
admin  0.078GB
local  4.076GB
mydb   0.078GB
test   0.078GB
rs0:PRIMARY> use mydb
switched to db mydb
rs0:PRIMARY> 
rs0:PRIMARY> db.coll.insert({"id":1})
WriteResult({ "nInserted" : 1 })
rs0:PRIMARY> 
rs0:PRIMARY> db.coll.find()
{ "_id" : ObjectId("5553670b60be2bf611868985"), "id" : 1 }
rs0:PRIMARY> 
rs0:PRIMARY> db.coll.remove({"id":1})
WriteResult({ "nRemoved" : 1 })
rs0:PRIMARY> 


【现在到分库中】

192.168.1.12(mongodb12.kk.net)

192.168.1.13(mongodb13.kk.net)


查看分库数据库目录,发现多了几个数据库,数据库与主库(192.168.1.11)一致!是主库同步过来的。

[root@mongodb12 ~]# ll /var/lib/mongo/

[root@mongodb13 ~]# ll /var/lib/mongo/
total 2423844
-rw-------. 1 mongod mongod   67108864 May 13 21:55 admin.0
-rw-------. 1 mongod mongod   16777216 May 13 21:55 admin.ns
drwxr-xr-x. 2 mongod mongod       4096 May 13 21:55 journal
-rw-------. 1 mongod mongod   67108864 May 13 21:55 local.0
-rw-------. 1 mongod mongod 2146435072 May 13 23:00 local.1
-rw-------. 1 mongod mongod   16777216 May 13 23:00 local.ns
-rwxr-xr-x. 1 mongod mongod          6 May 13 21:40 mongod.lock
-rw-------. 1 mongod mongod   67108864 May 13 23:00 mydb.0
-rw-------. 1 mongod mongod   16777216 May 13 23:00 mydb.ns
-rw-r--r--. 1 mongod mongod         69 May 12 22:05 storage.bson
-rw-------. 1 mongod mongod   67108864 May 13 21:55 test.0
-rw-------. 1 mongod mongod   16777216 May 13 21:55 test.ns
drwxr-xr-x. 2 mongod mongod       4096 May 13 21:55 _tmp

在副本服务器中登录其本地数据库,发现可以连接,但是无法读写操作:

[root@mongodb12 ~]# mongo 192.168.1.12:27018
MongoDB shell version: 3.0.2
connecting to: 192.168.1.12:27018/test
rs0:SECONDARY> 

从库开启读操作(此时可以测试主库插入,从库查看,同步正常):

rs0:SECONDARY> rs.slaveOk();


现在模拟主库不可用,将主节点服务停止:

[root@mongodb11 ~]# service mongod stop


到节点192.168.1.12 中登录mongodb,查看复制集状态:

rs0:SECONDARY> rs.status()
{
	"set" : "rs0",
	"date" : ISODate("2015-05-13T15:44:00.883Z"),
	"myState" : 2,
	"members" : [
		{
			"_id" : 0,
			"name" : "mongodb11.kk.net:27017",
			"health" : 0,
			"state" : 8,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : Timestamp(0, 0),
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2015-05-13T15:43:58.977Z"),
			"lastHeartbeatRecv" : ISODate("2015-05-13T15:42:16.467Z"),
			"pingMs" : 0,
			"lastHeartbeatMessage" : "Failed attempt to connect to mongodb11.kk.net:27017; couldn't connect to server mongodb11.kk.net:27017 (192.168.1.11), connection attempt failed",
			"configVersion" : -1
		},
		{
			"_id" : 1,
			"name" : "mongodb12.kk.net:27018",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 7431,
			"optime" : Timestamp(1431529249, 1),
			"optimeDate" : ISODate("2015-05-13T15:00:49Z"),
			"configVersion" : 3,
			"self" : true
		},
		{
			"_id" : 2,
			"name" : "mongodb13.kk.net:27019",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 6486,
			"optime" : Timestamp(1431529249, 1),
			"optimeDate" : ISODate("2015-05-13T15:00:49Z"),
			"lastHeartbeat" : ISODate("2015-05-13T15:44:00.530Z"),
			"lastHeartbeatRecv" : ISODate("2015-05-13T15:44:00.091Z"),
			"pingMs" : 0,
			"electionTime" : Timestamp(1431531738, 1),
			"electionDate" : ISODate("2015-05-13T15:42:18Z"),
			"configVersion" : 3
		}
	],
	"ok" : 1
}


以上信息看到:

原来的主实例(mongodb11.kk.net:27017 )已经无法连接了;

而其中一个节点(mongodb12.kk.net:27019 )变成了主实例,此时该节点是可以读写数据的;


启动服务器 mongodb11.kk.net 的mongodb服务,其变为了副本 (SECONDARY)。


如果想切换回原来的主库,参考:Force a Member to Become Primary

1. 使用命令rs.status() 确认数据集成员运行正常

2. 到次节点192.168.1.12(mongodb12.kk.net)中登录mongodb,运行freeze使其120内不会变为主节点。
rs.freeze(120)

3. 到主节点192.168.1.13(mongodb13.kk.net)中强制切换主节点,stepDown将阻止长事务和写入操作
rs.stepDown(120)

此时节点192.168.1.11(mongodb11.kk.net)变成主节点


若要使某个节点永远不会变为主节点,设置优先级为0。(参考 Prevent Secondary from Becoming Primary

cfg = rs.conf()
cfg.members[0].priority = 0.5
cfg.members[1].priority = 0.5
cfg.members[2].priority = 0
rs.reconfig(cfg)


说明:其中成员编号 0/1/2 为 rs.status()中的 "_id"值
members[2]为192.168.1.13(mongodb13.kk.net),则它将用于不会变成主节点


移除一个复制成员(两种方法):

登录到主库: mongodb11.kk.net ,移除成员

rs.remove("mongodb13.kk.net:27019")


或者:

cfg = rs.conf()
cfg.members.splice(2,1)
rs.reconfig(cfg)

移除后到移除的服务器,更改配置文件 /etc/mongod.conf

#replSet=rs0  #注释

再重启服务,完成移除(数据库文件仍保留在当前服务器)。



更多参考:

Replica Set Deployment Tutorials


Deploy a Replica Set

Deploy a Replica Set for Testing and Development


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。