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