mongodb之replSet复制集
复制集是一个带有故障转移的主从集群。是从现有的主从模式演变而来,增加了自动故障转移和节点成员自动恢复。
复制集模式中没有固定的主结点,在启动后,多个服务节点间将自动选举产生一个主结点。该主结点被称为primary,一个或多个从结点被称为secondaries。primary结点基本上就是master结点,不同之处在于primary结点在不同时间可能是不同的服务器。如果当前的主结点失效了,复制集中的其余结点将会试图选出一个新的主结点。
复制集模式的好处是,一切自动化。首先,复制集模式本身做了大量的管理工作,自动管理从节点,确保数据不会不一致。其次,主节点挂掉后,会自动判断集群中的服务器并进行故障转移,推举新的主节点。一个复制集集群支持1-7台服务器,在一个复制集中各个服务器数据保持完全一致。
在一个复制集集群中,各个服务器有以下几种状态:
Primary 主节点,一个复制集有且仅有一台服务器处于Primary状态,只有主节点才对外提供读写服务。如果主节点挂掉,复制集将会投票选出一个备用节点成为新的主节点。
Secondary 备用节点,复制集允许有多台Secondary,每个备用节点的数据与主节点的数据是完全同步的。
Recovering 恢复中,当复制集中某台服务器挂掉或者掉线后数据无法同步,重新恢复服务后从其他成员复制数据,这时就处于恢复过程,数据同步后,该节点又回到备用状态。
Arbiter 仲裁节点,该类节点可以不用单独存在,如果配置为仲裁节点,就主要负责在复本集中监控其他节点状态,投票选出主节点。该节点将不会用于存放数据。如果没有仲裁节点,那么投票工作将由所有节点共同进行。
Down 无效节点,当服务器挂掉或掉线时就会处于该状态。
复制集的从节点读请求,也是在各个Driver层设置slaveOk的值来实现的。
操作系统环境如下:
OS:Centos6.4 64bit IP:192.168.33.131
此次操作均在同一台机器上操作,安装mongodb请参考mongodb2.6安装编,然后建立复制集相对应的目录以及log日志文件等等
1:目录规划如下:
[root@localhost opt]# pwd /opt [root@localhost opt]# tree . . ├── logs ├── rs0 ├── rs1 └── rs2 4 directories, 0 files
2:因为在此服务器上需要配置replSet复制集,所以不使用默认的配置文件以及服务,需要但对建立配置文件以及更改相应的,目录文件日志文件等等
mongod对应ip地址以及端口如下:
mongod-IP Port 192.168.33.131 30000//主 192.168.33.131 30001//从 192.168.33.131 30002//从
3:mongodb各个配置文件如下:
mongodb-30000配置文件
# grep '^[a-Z]' /etc/30000.conf
logpath=/opt/log/rs0.log #日志文件
logappend=true #日志以追加模式
fork = true #后台启动
port = 30000#端口号
dbpath=/opt/rs0#mongodb数据目录
pidfilepath = /opt/rs0/30000.pid#mongodb-pid
master = true #是否参加选举
replSet = zxl#复制集名称
rest = true#mongodb接口,web界面访问
mongodb-30001配置文件
# grep '^[a-Z]' /etc/30001.conf
logpath=/opt/log/rs1.log
logappend=true
fork = true
port = 30001
dbpath=/opt/rs1
pidfilepath = /opt/rs1/30001.pid
master = true
replSet = zxl
mongodb-30002配置文件
# grep '^[a-Z]' /etc/30002.conf
logpath=/opt/log/rs2.log
logappend=true
fork = true
port = 30002
dbpath=/opt/rs2
pidfilepath = /opt/rs2/30002.pid
master = true
replSet = zxl
4:启动各个mongodb节点,方式如下:
mongodb端口30000启动
# mongod -f /etc/30000.conf about to fork child process, waiting until server is ready for connections. forked process: 1968 all output going to: /opt/log/rs0.log child process started successfully, parent exiting # netstat -ntpl|grep :2000 tcp 0 0 0.0.0.0:30000 0.0.0.0:* LISTEN 1968/mongod
mongodb端口30001启动
# mongod -f /etc/30001.conf about to fork child process, waiting until server is ready for connections. forked process: 2033 all output going to: /opt/log/rs1.log child process started successfully, parent exiting # netstat -ntpl|grep :2000 tcp 0 0 0.0.0.0:30000 0.0.0.0:* LISTEN 1968/mongod tcp 0 0 0.0.0.0:30001 0.0.0.0:* LISTEN 2033/mongod
mongodb端口30002启动
# mongod -f /etc/30002.conf about to fork child process, waiting until server is ready for connections. forked process: 2083 all output going to: /opt/log/rs2.log child process started successfully, parent exiting # netstat -ntpl|grep :2000 tcp 0 0 0.0.0.0:30000 0.0.0.0:* LISTEN 1968/mongod tcp 0 0 0.0.0.0:30001 0.0.0.0:* LISTEN 2033/mongod tcp 0 0 0.0.0.0:30002 0.0.0.0:* LISTEN 2083/mongod
机器实际操作如下:
终端方式只是测试启动各个replica sets,此方式与上面是一样,只不过我没有使用配置文件方式启动,生产环境请使用配置文件方式启动!下面方式启动各个mongod实例是一样的!
[root@localhost opt]# mongod --replSet zxl --dbpath=/opt/rs0/ --logpath=/opt/logs/rs0.log --logappend --port 30000 --fork about to fork child process, waiting until server is ready for connections. forked process: 1671 child process started successfully, parent exiting [root@localhost opt]# mongod --replSet zxl --dbpath=/opt/rs1/ --logpath=/opt/logs/rs1.log --logappend --port 30001 --fork about to fork child process, waiting until server is ready for connections. forked process: 1717 child process started successfully, parent exiting [root@localhost opt]# mongod --replSet zxl --dbpath=/opt/rs2/ --logpath=/opt/logs/rs2.log --logappend --port 30002 --fork about to fork child process, waiting until server is ready for connections. forked process: 1764 child process started successfully, parent exiting [root@localhost opt]#
5:登录mongodb端口为30000
[root@localhost opt]# mongo --port 30000 MongoDB shell version: 2.6.11 connecting to: 127.0.0.1:30000/test > db test
注:以下是添加复制集的主机,id:zxl复制集的名称,相当于一个小组。{_id:0,host: '192.168.33.131:30000'}是添加对应的id以及主机ip和端口,默认先添加谁,谁就是主,如果设置优先级就另说了.....
> cfg={_id:'zxl',members:[ ... {_id:0,host: '192.168.33.131:30000'}, ... {_id:1,host: '192.168.33.131:30001'}, ... {_id:2,host: '192.168.33.131:30002'}] ... } { "_id" : "zxl", "members" : [ { "_id" : 0, "host" : "192.168.33.131:30000" }, { "_id" : 1, "host" : "192.168.33.131:30001" }, { "_id" : 2, "host" : "192.168.33.131:30002" } ] } > rs.initiate(cfg) { "info" : "Config now saved locally. Should come online in about a minute.", "ok" : 1 } 注:初始化 [22:3:2]> rs.initiate(cfg) [22:3:2]{ [22:3:2] "info" : "Config now saved locally. Should come online in about a minute.", [22:3:2] "ok" : 1 [22:3:2]} 注:显示状态 > rs.status() { "set" : "zxl", "date" : ISODate("2015-12-13T21:48:42Z"), "myState" : 1, "members" : [ { "_id" : 0, "name" : "192.168.33.131:30000", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 140, "optime" : Timestamp(1450043304, 1), "optimeDate" : ISODate("2015-12-13T21:48:24Z"), "electionTime" : Timestamp(1450043313, 1), "electionDate" : ISODate("2015-12-13T21:48:33Z"), "self" : true }, { "_id" : 1, "name" : "192.168.33.131:30001", "health" : 1, "state" : 5, "stateStr" : "STARTUP2", "uptime" : 17, "optime" : Timestamp(0, 0), "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2015-12-13T21:48:41Z"), "lastHeartbeatRecv" : ISODate("2015-12-13T21:48:41Z"), "pingMs" : 0, "lastHeartbeatMessage" : "initial sync need a member to be primary or secondary to do our initial sync" }, { "_id" : 2, "name" : "192.168.33.131:30002", "health" : 1, "state" : 5, "stateStr" : "STARTUP2", "uptime" : 17, "optime" : Timestamp(0, 0), "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2015-12-13T21:48:41Z"), "lastHeartbeatRecv" : ISODate("2015-12-13T21:48:42Z"), "pingMs" : 0, "lastHeartbeatMessage" : "initial sync need a member to be primary or secondary to do our initial sync" } ], "ok" : 1 }
注:以上显示各个复制集的主机信息以及是否主或者从等等信息
6:查看是否是主的master的信息如下
zxl:PRIMARY> db.isMaster() { "setName" : "zxl", "setVersion" : 1, "ismaster" : true, "secondary" : false, "hosts" : [ "192.168.33.131:30000", "192.168.33.131:30002", "192.168.33.131:30001" ], "primary" : "192.168.33.131:30000", "me" : "192.168.33.131:30000", "electionId" : ObjectId("566de7b2a25a61b157882302"), "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2015-12-13T21:48:58.224Z"), "maxWireVersion" : 2, "minWireVersion" : 0, "ok" : 1 }
创建一个数据库ceshi,并插入数据
zxl:PRIMARY> use ceshi switched to db ceshi zxl:PRIMARY> db ceshi zxl:PRIMARY> db.a.insert({name:"xiaoer",age:33}) WriteResult({ "nInserted" : 1 })
7:mongodb端口30001登录,已经显示为从节点
[root@localhost ~]# mongo --port 30001 MongoDB shell version: 2.6.11 connecting to: 127.0.0.1:30001/test zxl:SECONDARY> db test
也可以在从节点查看是否为master命令如下:
zxl:SECONDARY> db.isMaster() { "setName" : "zxl", "setVersion" : 1, "ismaster" : false, "secondary" : true, "hosts" : [ "192.168.33.131:30001", "192.168.33.131:30002", "192.168.33.131:30000" ], "primary" : "192.168.33.131:30000", "me" : "192.168.33.131:30001", "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2015-12-13T21:51:55.807Z"), "maxWireVersion" : 2, "minWireVersion" : 0, "ok" : 1 }
此时从节点是没有查询权限,需进行rs.slaveOk()即可
zxl:SECONDARY> rs.slaveOk() zxl:SECONDARY> show tables; a system.indexes zxl:SECONDARY> db.a.find() { "_id" : ObjectId("566de8054436414a1c849a93"), "name" : "xiaoer", "age" : 33 }
8:把主节点端口为30000的停止,看从节点是否成为主的,操作如下
zxl:PRIMARY> use admin switched to db admin zxl:PRIMARY> db.shutdownServer() 2015-12-14T06:15:18.778+0800 DBClientCursor::init call() failed server should be down... 2015-12-14T06:15:18.781+0800 trying reconnect to 127.0.0.1:30000 (127.0.0.1) failed 2015-12-14T06:15:18.782+0800 warning: Failed to connect to 127.0.0.1:30000, reason: errno:111 Connection refused 2015-12-14T06:15:18.782+0800 reconnect 127.0.0.1:30000 (127.0.0.1) failed failed couldn't connect to server 127.0.0.1:30000 (127.0.0.1), connection attempt failed 2015-12-14T06:15:18.786+0800 trying reconnect to 127.0.0.1:30000 (127.0.0.1) failed 2015-12-14T06:15:18.787+0800 warning: Failed to connect to 127.0.0.1:30000, reason: errno:111 Connection refused 2015-12-14T06:15:18.787+0800 reconnect 127.0.0.1:30000 (127.0.0.1) failed failed couldn't connect to server 127.0.0.1:30000 (127.0.0.1), connection attempt failed > exit bye 9:登录从节点端口30001、30002,并分别登录如下 [root@localhost ~]# mongo --port 30001 MongoDB shell version: 2.6.11 connecting to: 127.0.0.1:30001/test zxl:SECONDARY> zxl:PRIMARY> db.isMaster() { "setName" : "zxl", "setVersion" : 1, "ismaster" : true, "secondary" : false, "hosts" : [ "192.168.33.131:30001", "192.168.33.131:30002", "192.168.33.131:30000" ], "primary" : "192.168.33.131:30001", "me" : "192.168.33.131:30001", "electionId" : ObjectId("566dedfbdc32e033bb4d0e18"), "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2015-12-13T22:16:10.788Z"), "maxWireVersion" : 2, "minWireVersion" : 0, "ok" : 1 }
30002登陆查看
[root@localhost ~]# mongo --port 30002 MongoDB shell version: 2.6.11 connecting to: 127.0.0.1:30002/test zxl:SECONDARY> db.isMaster() { "setName" : "zxl", "setVersion" : 1, "ismaster" : false, "secondary" : true, "hosts" : [ "192.168.33.131:30002", "192.168.33.131:30001", "192.168.33.131:30000" ], "primary" : "192.168.33.131:30001", "me" : "192.168.33.131:30002", "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2015-12-13T22:17:57.891Z"), "maxWireVersion" : 2, "minWireVersion" : 0, "ok" : 1 }
注:此时端口30001的已经成为主节点,进行插入数据等等
zxl:PRIMARY> use ceshi switched to db ceshi zxl:PRIMARY> show tables; a system.indexes zxl:PRIMARY> db.a.insert({a:1}) WriteResult({ "nInserted" : 1 }) zxl:PRIMARY> db.a.find() { "_id" : ObjectId("566de8054436414a1c849a93"), "name" : "xiaoer", "age" : 33 } { "_id" : ObjectId("566def04cbb79452107c217f"), "a" : 1 }
登录另一个端口30002的进行查看,操作如下:
zxl:SECONDARY> show dbs admin (empty) ceshi 0.078GB local 1.078GB test (empty) zxl:SECONDARY> use ceshi switched to db ceshi zxl:SECONDARY> show tables; 2015-12-14T06:20:29.891+0800 error: { "$err" : "not master and slaveOk=false", "code" : 13435 } at src/mongo/shell/query.js:131 zxl:SECONDARY> rs.slaveOk() zxl:SECONDARY> show tables; a system.indexes zxl:SECONDARY> db.a.find() { "_id" : ObjectId("566de8054436414a1c849a93"), "name" : "xiaoer", "age" : 33 } { "_id" : ObjectId("566def04cbb79452107c217f"), "a" : 1 } zxl:SECONDARY>
注:以上可以进行查询到端口30001的新的节点数据,但是从节点30002,查询时出现错误,需要设置为rs.slaveOk()即可,不过配置文件是可以设置的。
以上就是mongodb replSet复制集