一. MongoDB复制集特点:
1. 由一组Mongod实例组成, 可以在一台机器上, 也可以在多台机器上,甚至可以在多个机房。
2. PRIMAY节点承担写请求,而SECONDARY通过同步数据来让集群内数据一致, 并且SECONDARY节点 可以担读请求(需在连接会话里设置db.getMongo().setSlaveOk();)
如果要为MONGODB 建立异地容灾, 可考虑在异地机房建立SECONDARY 节点,保证数据冗余。
注: 在设置异地节点时,我们需要考虑一个问题,应用是否会发现这个节点,如果会,我们又该如何规避这个问题?
二. MongoDB复制集的角色:
Primary: 承担所有请求,一个复制集里只能有一个主库。
Secondary: 同步数据,在主库出现问时,可切为主库, 以如下三种Secondary类型:
Priority:0 只同步数据, 不会被切为主库。
Hidden:true 同步数据,并且不会被应用程序节点所识别到。
slaveDelay:3600 保持延迟一个小时, 在设置此类型的SECONDARY节点时,必须保证不会被切为主库,并且不被应用程序所识别。
Arbiter: 不同步数据,只参与投票,且不能作为Primary.
思考:
在MONGODB的复制集中是没有VIP的概念的, 那么我们如何设置能够保证在主节点出问题时应用能够继续正常服务?
三. 正确使用MONGODB 复制集的姿势:
如:这里是使用一主两SECONDARY节点, 而其中有一个节点为异地机房, 且设置成为了隐藏属性。
>>> import pymongo
>>> from pymongo import MongoClient
>>> MongoClient("mongodb://192.168.1.51:27027,192.168.1.52:27027", replicaSet='pktest')
MongoClient(host=['192.168.1.51:27027', '192.168.1.52:27027'], document_class=dict, tz_aware=False, connect=True, replicaset='pktest')
>>> db=MongoClient("mongodb://192.168.1.51:27027,192.168.1.52:27027", replicaSet='pktest').test
>>> db.test.find_one()
{u'a': 11L, u'_id': 1L}
模拟主库DOWN掉:
pktest:PRIMARY> use admin; switched to db admin pktest:PRIMARY> db.shutdownServer() 2016-12-21T17:24:22.103+0800 I NETWORK DBClientCursor::init call() failed server should be down... 2016-12-21T17:24:22.105+0800 I NETWORK trying reconnect to 127.0.0.1:27027 (127.0.0.1) failed 2016-12-21T17:24:22.105+0800 I NETWORK reconnect 127.0.0.1:27027 (127.0.0.1) ok 2016-12-21T17:24:22.722+0800 I NETWORK Socket recv() errno:104 Connection reset by peer 127.0.0.1:27027 2016-12-21T17:24:22.722+0800 I NETWORK SocketException: remote: 127.0.0.1:27027 error: 9001 socket exception [RECV_ERROR] server [127.0.0.1:27027] 2016-12-21T17:24:22.722+0800 I NETWORK DBClientCursor::init call() failed 2016-12-21T17:24:22.725+0800 I NETWORK trying reconnect to 127.0.0.1:27027 (127.0.0.1) failed 2016-12-21T17:24:22.725+0800 W NETWORK Failed to connect to 127.0.0.1:27027, reason: errno:111 Connection refused 2016-12-21T17:24:22.725+0800 I NETWORK reconnect 127.0.0.1:27027 (127.0.0.1) failed failed couldn't connect to server 127.0.0.1:27027 (127.0.0.1), connection attempt failed >
再次去查数据库:
>>> db.test.find_one()
{u'a': 11L, u'_id': 1L}
>>> db.test.find_one()
{u'a': 11L, u'_id': 1L}
>>> db.test.find_one()
{u'a': 11L, u'_id': 1L}
>>> db=MongoClient("mongodb://192.168.1.51:27027,192.168.1.52:27027", replicaSet='pktest').test
>>> db.test.find_one()
{u'a': 11L, u'_id': 1L}
节点数 | 允许失效数 |
3 | 1 |
5 | 2 |
7 | 3 |
9 | 4 |
11 | 5 |
服务器IP | 复制集角色 |
192.168.1.77 | Primay |
192.168.1.78 | Secondary |
192.168.1.51 | Secondary(异地机房) |
dbpath = /data/dbdata/mongodb_27017/data directoryperdb = true #master = true port = 27017 fork = true logappend = true logpath = /data/dbdata/mongodb_27017/mongodb_27017.log journal = true nohttpinterface = true cpu = true #Replica Set oplogSize = 2000 replSet = rstest
/apps/svr/mongo2.6/bin/mongod -f /apps/conf/mongo_27017.cnf
[root@VM-1-77 conf]# /apps/svr/mongo2.6/bin/mongo 127.0.0.1:27017 MongoDB shell version: 2.6.12 connecting to: 127.0.0.1:27017/test > config={_id:"rstest",members:[{_id:0, host:"192.168.1.77"},{_id:1, host:"192.168.1.78"},{_id:2, host:"192.168.1.51",hidden:true, priority:0}]} #设置复制集节点 { "_id" : "rstest", "members" : [ { "_id" : 0, "host" : "192.168.1.77" }, { "_id" : 1, "host" : "192.168.1.78" }, { "_id" : 2, "host" : "192.168.1.51", "hidden" : true, "priority" : 0 } ] } > rs.initiate(config) #初始化复制集的配置 { "info" : "Config now saved locally. Should come online in about a minute.", "ok" : 1 } > rs.conf() #查看复制集的成员以及成员属性 { "_id" : "rstest", "version" : 1, "members" : [ { "_id" : 0, "host" : "192.168.1.77:27017" }, { "_id" : 1, "host" : "192.168.1.78:27017" }, { "_id" : 2, "host" : "192.168.1.51:27017", "priority" : 0, "hidden" : true } ] } rstest:PRIMARY> rs.status() #查看复制集状态 { "set" : "rstest", "date" : ISODate("2016-12-21T10:42:25Z"), "myState" : 1, "members" : [ { "_id" : 0, "name" : "192.168.1.77:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 391, "optime" : Timestamp(1482316913, 1), "optimeDate" : ISODate("2016-12-21T10:41:53Z"), "electionTime" : Timestamp(1482316924, 1), "electionDate" : ISODate("2016-12-21T10:42:04Z"), "self" : true }, { "_id" : 1, "name" : "192.168.1.78:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 29, "optime" : Timestamp(1482316913, 1), "optimeDate" : ISODate("2016-12-21T10:41:53Z"), "lastHeartbeat" : ISODate("2016-12-21T10:42:24Z"), "lastHeartbeatRecv" : ISODate("2016-12-21T10:42:24Z"), "pingMs" : 2, "syncingTo" : "192.168.1.77:27017" }, { "_id" : 2, "name" : "192.168.1.51:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 29, "optime" : Timestamp(1482316913, 1), "optimeDate" : ISODate("2016-12-21T10:41:53Z"), "lastHeartbeat" : ISODate("2016-12-21T10:42:24Z"), "lastHeartbeatRecv" : ISODate("2016-12-21T10:42:24Z"), "pingMs" : 1, "syncingTo" : "192.168.1.77:27017" } ], "ok" : 1 } rstest:PRIMARY>
[root@VM-1-77]# /apps/svr/mongo2.6/bin/mongo 127.0.0.1:27017 MongoDB shell version: 2.6.12 connecting to: 127.0.0.1:27017/test rstest:PRIMARY> for(i=0;i<20;i++){db.scores.save({student:i,score:20})}; WriteResult({ "nInserted" : 1 }) rstest:PRIMARY> db.scores.count(); 20
从库查询:
[root@VM-1-78 ]# /apps/svr/mongo2.6/bin/mongo 127.0.0.1:27017 MongoDB shell version: 2.6.12 connecting to: 127.0.0.1:27017/test rstest:SECONDARY> db.getMongo().setSlaveOk(); rstest:SECONDARY> db.scores.count(); 20 rstest:SECONDARY>