Title

MongoDB 复制集

参考 MongoDB学习札记第八篇之Replica Set 实战
参考 MongoDB 3.0 复制集集群搭建及安全认证实践
参考 MongoDB 3.0 WT引擎参考配置文件
参考 MongoDB 副本集的原理. 搭建. 应用

准备三台mongo服务器 分别为 43.241.222.110 42.96.194.60 和 45.63.50.67 搭建复制集

如果对于怎么安装Mongodb还不清楚的同学可以查看我之前的学习札记

三台MongoDB服务器的配置文件均为 /etc/mongod.cnf

storage:
    dbPath: "/data/home/data/RSMongoDB"
    engine: wiredTiger
    wiredTiger:
        engineConfig:
            cacheSizeGB: 20
        collectionConfig:
            blockCompressor: snappy

systemLog:
   destination: file
   path: "/var/log/mongodb/mongod.log"
   logAppend: true

processManagement:
    fork: true

net:
    #bindIp: 127.0.0.1,43.241.222.110,42.96.194.60  不能绑定外网访问ip,局域网的貌似可以,只能在iptable设定允许指定ip访问27017
    #bindIp: 0.0.0.0
    port: 27017
    # Enable the HTTP interface (Defaults to port 28017).
    http:
        enabled: false

第一步:

在三台机器上分别运行(都要运行)

root@ubuntu:/usr/local/mongodb#mongod -f /etc/mongod.cnf --replSet CoamReSet

注意这里的 —replSet 参数指定了副本集的名称,每一个副本集都有一个唯一的名称.

等到三台机器都启动完了之后.使用mongo客户端登录其中一台mongod服务器.这里我登录到 43.241.222.110 这台机器

root@ubuntu:~# mongo

登录之后要切换到admin数据库,这样我们可以进行副本集的配置,具体怎么配置,代码如下:

> use admin
switched to db admin

定义副本集配置变量,这里的 _id:”repset” 和上面命令参数 “ –replSet repset” 要保持一样.

> config = {_id:"CoamReSet",members:[
         {_id:0,host:"43.241.222.110:27017","priority":1},
         {_id:1,host:"42.96.194.60:27017","priority":1},
         {_id:2,host:"45.63.50.67:27017","priority":0}]}

输出

{
    "_id" : "CoamReSet",
    "members" : [
        {
            "_id" : 0,
            "host" : "43.241.222.110:27017"
        },
        {
            "_id" : 1,
            "host" : "42.96.194.60:27017"
        },
        {
            "_id" : 2,
            "host" : "45.63.50.67:27017"
        }
    ]
}

初始化副本集配置

> rs.initiate(config);

输出成功

{ "ok" : 1 }

注意:新创建副本集必须要数据库没有数据,否则初始化会提示以下错误:

{
    "ok" : 0,
    "errmsg" : "'42.96.194.60:27017' has data already, cannot initiate set.",
    "code" : 110
}

先定义 config 的配置信息, 然后通过 rs.initiate(config) 方法,将配置信息初始化.这两个步骤完成之后就表示我们的副本集配置信息初始化完成了,在这个CoamReSet的副本集中我们定义了三台主机(注意在定义配置信息的时候指定的 _id 必须和我们启动mongod的时候指定的参数 —replSet 这个参数的值是一样的.)

过一会,mongodb就会帮我们选举出Primary节点和Secondary节点了.那在mongo客户端,我们可以通过 rs.status() 来查看副本集的状态信息

CoamReSet:SECONDARY> rs.status()
{
    "set" : "CoamReSet",
    "date" : ISODate("2015-10-01T09:45:34.924Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 0,
            "name" : "43.241.222.110:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 167,
            "optime" : Timestamp(1443692712, 1),
            "optimeDate" : ISODate("2015-10-01T09:45:12Z"),
            "electionTime" : Timestamp(1443692715, 1),
            "electionDate" : ISODate("2015-10-01T09:45:15Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "42.96.194.60:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 21,
            "optime" : Timestamp(1443692712, 1),
            "optimeDate" : ISODate("2015-10-01T09:45:12Z"),
            "lastHeartbeat" : ISODate("2015-10-01T09:45:33.166Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T09:45:33.564Z"),
            "pingMs" : 16,
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "45.63.50.67:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 21,
            "optime" : Timestamp(1443692712, 1),
            "optimeDate" : ISODate("2015-10-01T09:45:12Z"),
            "lastHeartbeat" : ISODate("2015-10-01T09:45:32.949Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T09:45:33.973Z"),
            "pingMs" : 183,
            "configVersion" : 1
        }
    ],
    "ok" : 1
}

其中name表示我么你的主机, health表示主机是否健康(0/1) , state(主节点(1)还是从节点(2),或者是不可达节点)

如果上面信息正常显示出来说明整个副本集群已经建立起来了.这时候我们来验证一下是否是真的能够自动备份数据,是否能够自动从失败中恢复,自动选举新的Primary节点.
这个实验我们这样来做:

先往 Primary 节点(43.241.222.110)插入数据,在 42.96.194.60 和 45.63.50.67 两台 Secondary 节点中查询数据,验证是否能够正常的同步机器.

先往 Primary 节点(43.241.222.110)插入数据

CoamReSet:PRIMARY> use test
switched to db test
CoamReSet:PRIMARY> show collections
CoamReSet:PRIMARY> db.guids.insert({"name":"replica set","author":"webinglin"})
WriteResult({ "nInserted" : 1 })
CoamReSet:PRIMARY> exit
bye

在 45.63.50.67 Secondary 节点中查询数据,验证是否能够正常的同步机器.

root@ubuntu:~# mongo --host 45.63.50.67
MongoDB shell version: 3.0.3
connecting to: 45.63.50.67:27017/test
Server has startup warnings:
2015-06-09T17:03:27.744-0700 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not re                                      commended.
2015-06-09T17:03:27.744-0700 I CONTROL  [initandlisten]
2015-06-09T17:03:27.745-0700 I CONTROL  [initandlisten]
2015-06-09T17:03:27.745-0700 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2015-06-09T17:03:27.745-0700 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2015-06-09T17:03:27.745-0700 I CONTROL  [initandlisten]
CoamReSet:SECONDARY> show dbs
2015-06-09T17:13:49.138-0700 E QUERY    Error: listDatabases failed:{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" }
    at Error (<anonymous>)
    at Mongo.getDBs (src/mongo/shell/mongo.js:47:15)
    at shellHelper.show (src/mongo/shell/utils.js:630:33)
    at shellHelper (src/mongo/shell/utils.js:524:36)
    at (shellhelp2):1:1 at src/mongo/shell/mongo.js:47
CoamReSet:SECONDARY> use test
switched to db test
CoamReSet:SECONDARY> db.guids.find()
Error: error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
CoamReSet:SECONDARY> rs.slaveOk()
CoamReSet:SECONDARY> rs.slaveOk()
CoamReSet:SECONDARY> db.guids.find()
{ "_id" : ObjectId("557780ebd147e9391020860d"), "name" : "replica set", "author" : "webinglin" }
CoamReSet:SECONDARY> show collections()
2015-06-09T17:14:24.219-0700 E QUERY    Error: don't know how to show [collections()]
    at Error (<anonymous>)
    at shellHelper.show (src/mongo/shell/utils.js:733:11)
    at shellHelper (src/mongo/shell/utils.js:524:36)
    at (shellhelp2):1:1 at src/mongo/shell/utils.js:733
CoamReSet:SECONDARY> show collections
guids
system.indexes
CoamReSet:SECONDARY> exit
bye

在 42.96.194.60 Secondary 节点中查询数据,验证是否能够正常的同步机器.

root@ubuntu:~# mongo --host 42.96.194.60
MongoDB shell version: 3.0.3
connecting to: 42.96.194.60:27017/test
Server has startup warnings:
2015-06-09T17:03:11.647-0700 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not re                                      commended.
2015-06-09T17:03:11.647-0700 I CONTROL  [initandlisten]
2015-06-09T17:03:11.647-0700 I CONTROL  [initandlisten]
2015-06-09T17:03:11.648-0700 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2015-06-09T17:03:11.648-0700 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2015-06-09T17:03:11.648-0700 I CONTROL  [initandlisten]
CoamReSet:SECONDARY> rs.slaveOk()
CoamReSet:SECONDARY> show dbs
local  1.078GB
test   0.078GB
CoamReSet:SECONDARY> use test
switched to db test
CoamReSet:SECONDARY> show collections
guids
system.indexes
CoamReSet:SECONDARY> db.guids.find()
{ "_id" : ObjectId("557780ebd147e9391020860d"), "name" : "replica set", "author" : "webinglin" }
CoamReSet:SECONDARY> exit
bye

至此,整个验证过程说明了我们集群部署是成功的.数据能够正常同步了.
那么接下来我们还要验证另一种情况,Primary异常终止之后(43.241.222.110),另外两个Secondary节点会不会自动选举出新的Primary节点呢?
这个实验我们这样处理: 将 43.241.222.110 机器的mongod服务停止掉,然后再来连接 42.96.194.60 或者 45.63.50.67 任意一台机器,通过 rs.status() 查看集群状态.

在Primary节点(43.241.222.110)通过 ps -e | grep mongod 查看mongod服务是否开启,然后通过 killall mongod 或者 kill -15 <进程号> 来杀死mongod进程

root@ubuntu:~# ps -e | grep mongod
 3279 pts/0    00:00:19 mongod
root@ubuntu:~# killall mongod

登陆从节点 42.96.194.60 ,查看mongo服务器状态

root@ubuntu:~# mongo --host 42.96.194.60
MongoDB shell version: 3.0.3
connecting to: 42.96.194.60:27017/test
Server has startup warnings:
2015-06-09T17:03:11.647-0700 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2015-06-09T17:03:11.647-0700 I CONTROL  [initandlisten]
2015-06-09T17:03:11.647-0700 I CONTROL  [initandlisten]
2015-06-09T17:03:11.648-0700 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2015-06-09T17:03:11.648-0700 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2015-06-09T17:03:11.648-0700 I CONTROL  [initandlisten]
CoamReSet:SECONDARY> rs.status()
{
    "set" : "CoamReSet",
    "date" : ISODate("2015-10-01T10:09:57.981Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 0,
            "name" : "43.241.222.110: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-10-01T10:09:56.226Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T10:07:54.850Z"),
            "pingMs" : 18,
            "lastHeartbeatMessage" : "Failed attempt to connect to 43.241.222.110:27017; couldn't connect to server 43.241.222.110:27017 (43.241.222.110), connection attempt failed",            "configVersion" : -1
        },
        {
            "_id" : 1,
            "name" : "42.96.194.60:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 1577,
            "optime" : Timestamp(1443693679, 1),
            "optimeDate" : ISODate("2015-10-01T10:01:19Z"),
            "electionTime" : Timestamp(1443694079, 1),
            "electionDate" : ISODate("2015-10-01T10:07:59Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 2,
            "name" : "45.63.50.67:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 1481,
            "optime" : Timestamp(1443693679, 1),
            "optimeDate" : ISODate("2015-10-01T10:01:19Z"),
            "lastHeartbeat" : ISODate("2015-10-01T10:09:56.891Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T10:09:57.259Z"),
            "pingMs" : 440,
            "configVersion" : 1
        }
    ],
    "ok" : 1
}
CoamReSet:SECONDARY> exit
bye

通过上面这段代码的观察,我们发现,当把原来的Primary节点停止掉后(43.241.222.110停止), 那么整个mongodb的副本集群会重新选举出新的Primary节点( 42.96.194.60 机器)

为了验证一下新选举的Primary是否正常,我们再次验证一把数据的同步情况,先连接到 42.96.194.60 主节点,将原来的数据删掉,再到 45.63.50.67 SECONDARY 进行验证,数据是否也被删除

连接到 42.96.194.60 主节点,将原来的数据删掉

root@ubuntu:~# mongo --host 42.96.194.60
CoamReSet:PRIMARY> use test
switched to db test
CoamReSet:PRIMARY> show collections
guids
CoamReSet:PRIMARY> db.guids.find()
{ "_id" : ObjectId("560d03099548a3e5bb8b03bf"), "name" : "replica set", "author" : "webinglin" }
{ "_id" : ObjectId("560d046f9548a3e5bb8b03c0"), "name" : "zhang", "author" : "yafei..." }
CoamReSet:PRIMARY> db.guids.remove({name:"zhang"})
WriteResult({ "nRemoved" : 1 })
CoamReSet:PRIMARY> db.guids.find()
{ "_id" : ObjectId("560d03099548a3e5bb8b03bf"), "name" : "replica set", "author" : "webinglin" }
CoamReSet:PRIMARY> exit
bye

再到 45.63.50.67 SECONDARY 进行验证,数据是否也被删除

root@ubuntu:~# mongo --host 45.63.50.67
CoamReSet:SECONDARY> rs.slaveOk()
CoamReSet:SECONDARY> db.guids.find()
{ "_id" : ObjectId("557780ebd147e9391020860d"), "name" : "replica set", "author" : "webinglin" }
CoamReSet:SECONDARY> exit
bye

实践后发现,先选举的Primary节点也正常工作.我们的整个Mongodb副本集群测试完成.

动态添加节点,删除节点.

在开始这个实验之前,先把 43.241.222.110 的机器重新启动,然后用mongo客户端连到 43.241.222.110 进行验证数据是否也同步了.
登录 43.241.222.110 之后,我们发现数据也同步了,然后43.241.222.110节点变成了 Secondary 节点了.

root@ubuntu:~# mongo
CoamReSet:SECONDARY> rs.slaveOk()
CoamReSet:SECONDARY> show dbs
local   0.000GB
syData  0.000GB
test    0.000GB
CoamReSet:SECONDARY> use test
switched to db test
CoamReSet:SECONDARY> show collections
guids
CoamReSet:SECONDARY> db.guids.find()
{ "_id" : ObjectId("560d03099548a3e5bb8b03bf"), "name" : "replica set", "author" : "webinglin" }
CoamReSet:SECONDARY> rs.status()
{
    "set" : "CoamReSet",
    "date" : ISODate("2015-10-01T10:21:53.366Z"),
    "myState" : 2,
    "syncingTo" : "42.96.194.60:27017",
    "members" : [
        {
            "_id" : 0,
            "name" : "43.241.222.110:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 68,
            "optime" : Timestamp(1443694583, 1),
            "optimeDate" : ISODate("2015-10-01T10:16:23Z"),
            "syncingTo" : "42.96.194.60:27017",
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "42.96.194.60:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 66,
            "optime" : Timestamp(1443694583, 1),
            "optimeDate" : ISODate("2015-10-01T10:16:23Z"),
            "lastHeartbeat" : ISODate("2015-10-01T10:21:53.026Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T10:21:52.588Z"),
            "pingMs" : 16,
            "electionTime" : Timestamp(1443694079, 1),
            "electionDate" : ISODate("2015-10-01T10:07:59Z"),
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "45.63.50.67:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 66,
            "optime" : Timestamp(1443694583, 1),
            "optimeDate" : ISODate("2015-10-01T10:16:23Z"),
            "lastHeartbeat" : ISODate("2015-10-01T10:21:51.818Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T10:21:53.006Z"),
            "pingMs" : 311,
            "syncingTo" : "42.96.194.60:27017",
            "configVersion" : 1
        }
    ],
    "ok" : 1
}
CoamReSet:SECONDARY> exit
bye

登录到 42.96.194.60 Primary 节点,通过 rs.remove() 方法来删除副本集中的某一个节点,这里我们还是将 43.241.222.110 删除.删除之后我们还往 42.96.194.60 主节点中加入数据.

CoamReSet:PRIMARY> rs.remove("43.241.222.110:27017")
{ "ok" : 1 }
CoamReSet:PRIMARY> rs.status()
{
    "set" : "CoamReSet",
    "date" : ISODate("2015-10-01T10:24:35.061Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 1,
            "name" : "42.96.194.60:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 2455,
            "optime" : Timestamp(1443695065, 1),
            "optimeDate" : ISODate("2015-10-01T10:24:25Z"),
            "electionTime" : Timestamp(1443694079, 1),
            "electionDate" : ISODate("2015-10-01T10:07:59Z"),
            "configVersion" : 2,
            "self" : true
        },
        {
            "_id" : 2,
            "name" : "45.63.50.67:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 2358,
            "optime" : Timestamp(1443695065, 1),
            "optimeDate" : ISODate("2015-10-01T10:24:25Z"),
            "lastHeartbeat" : ISODate("2015-10-01T10:24:33.256Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T10:24:34.102Z"),
            "pingMs" : 334,
            "configVersion" : 2
        }
    ],
    "ok" : 1
}
CoamReSet:PRIMARY> db.guids.find()
{ "_id" : ObjectId("560d03099548a3e5bb8b03bf"), "name" : "replica set", "author" : "webinglin" }
CoamReSet:PRIMARY> db.guids.insert({"name":"remove one node dync"})
WriteResult({ "nInserted" : 1 })
CoamReSet:PRIMARY> db.guids.find()
{ "_id" : ObjectId("560d03099548a3e5bb8b03bf"), "name" : "replica set", "author" : "webinglin" }
{ "_id" : ObjectId("560d0a1d7d9deef6a0890b1f"), "name" : "remove one node dync" }
CoamReSet:PRIMARY> exit
bye

删除 43.241.222.110 节点后,我们往 Primary 节点中加入了新的数据,然后先不要将 43.241.222.110 的 mongod 服务停掉,我们通过mongo连接到 43.241.222.110 的mongod服务来查看数据

root@ubuntu:~# mongo --host 43.241.222.110
> db.guids.find()
{ "_id" : ObjectId("560d03099548a3e5bb8b03bf"), "name" : "replica set", "author" : "webinglin" }
> exit
bye

实验结果可以知道,我们在 45.63.50.67 新加入的数据 {name:”remove one node dync”} 并没有同步到43.241.222.110(已从副本集中删除).

为了让实验结果更加确切,我们查看 43.241.222.110 是否有同步了数据:

root@ubuntu:~# mongo –host 45.63.50.67
CoamReSet:SECONDARY> db.guids.find()
{ “_id” : ObjectId(“557780ebd147e9391020860d”), “name” : “replica set”, “author” : “webinglin” }
{ “_id” : ObjectId(“557785bcbb56172c8e069341”), “name” : “remove one node dync” }
CoamReSet:SECONDARY> exit
bye

实验数据可以看到, 45.63.50.67 同步了在 42.96.194.60 主节点中新增的文档 {“name”:”remove one node dync”},这样就证明了动态删除副本集中的某一个节点的实验成功了.那怎么动态添加节点到副本集中呢?

原理是一样的,但是调用的方法变成了 rs.add(“43.241.222.110:27017”)

CoamReSet:PRIMARY> rs.add("43.241.222.110:27017");
{ "ok" : 1 }
CoamReSet:PRIMARY> rs.status()
{
    "set" : "CoamReSet",
    "date" : ISODate("2015-10-01T10:32:45.284Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 1,
            "name" : "42.96.194.60:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 2945,
            "optime" : Timestamp(1443695560, 1),
            "optimeDate" : ISODate("2015-10-01T10:32:40Z"),
            "electionTime" : Timestamp(1443694079, 1),
            "electionDate" : ISODate("2015-10-01T10:07:59Z"),
            "configVersion" : 3,
            "self" : true
        },
        {
            "_id" : 2,
            "name" : "45.63.50.67:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 2849,
            "optime" : Timestamp(1443695560, 1),
            "optimeDate" : ISODate("2015-10-01T10:32:40Z"),
            "lastHeartbeat" : ISODate("2015-10-01T10:32:43.660Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T10:32:44.079Z"),
            "pingMs" : 452,
            "syncingTo" : "42.96.194.60:27017",
            "configVersion" : 2
        },
        {
            "_id" : 3,
            "name" : "43.241.222.110:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 2,
            "optime" : Timestamp(1443695560, 1),
            "optimeDate" : ISODate("2015-10-01T10:32:40Z"),
            "lastHeartbeat" : ISODate("2015-10-01T10:32:44.739Z"),
            "lastHeartbeatRecv" : ISODate("2015-10-01T10:32:43.300Z"),
            "pingMs" : 16,
            "syncingTo" : "42.96.194.60:27017",
            "configVersion" : 3
        }
    ],
    "ok" : 1
}
CoamReSet:PRIMARY> exit
bye

在rs.status()返回的结果中可以看到,43.241.222.110 节点已经成功加入副本集中了.加入之后,理论上应该会把在 43.241.222.110 主节点加入的数据同步过来,刚才删除之后是不会同步的.那这时候重新加入副本集,应该是要同步的.下面是实验结果:

root@ubuntu:~# mongo
CoamReSet:SECONDARY> db.guids.find()
{ "_id" : ObjectId("560d03099548a3e5bb8b03bf"), "name" : "replica set", "author" : "webinglin" }
{ "_id" : ObjectId("560d0a1d7d9deef6a0890b1f"), "name" : "remove one node dync" }
CoamReSet:SECONDARY> exit
bye

实验结果显示,动态添加操作也正常.动态的将 43.241.222.110 节点加入到副本集中能够保证数据同步成功.


注意

在调用 rs.add(“host:ip”) 或者 rs.remove(“host:ip”) 的时候,必须要在 Primary 节点中进行.

add方法可以加入一个document对象,这样就可以在指定具体的Secondary节点的更多的设置项了,比如指定为priority: 0 或 priority: 0,hidden: true 或 priority:0,hidden:true,arbiterOnly:true

{
  _id: <int>,
  host: <string>,
  arbiterOnly: <boolean>,
  buildIndexes: <boolean>,
  hidden: <boolean>,
  priority: <number>,
  tags: <document>,
  slaveDelay: <int>,
  votes: <number>
}

怎么对副本集进行权限验证,参考主从复制的安全部分,也是通过openssl来生成keyfile,然后再启动mongod的时候指定keyFile来设置安全的


也可以在三个主机的复制集添加以下配置

replication:
##oplog大小
 oplogSizeMB: 20
##复制集名称
 replSetName: CoamReSet

复制集优先级问题

默认设定节点 43.241.222.110 为Primary主节点,由于初始配置中没有设定,于是在主节点服务器重启后 43.241.222.110 自动切换成 从节点,而 42.96.194.60 切换成了主节点导致应用程序连接错误
于是在当前主节点 43.241.222.110 通过命令行手动切换主节点到 43.241.222.110

CoamReSet:PRIMARY> rs.status()
{
        "set" : "CoamReSet",
        "date" : ISODate("2015-10-09T11:28:28.585Z"),
        "myState" : 1,
        "members" : [
                {
                        "_id" : 1,
                        "name" : "42.96.194.60:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 614570,
                        "optime" : Timestamp(1444378212, 1),
                        "optimeDate" : ISODate("2015-10-09T08:10:12Z"),
                        "electionTime" : Timestamp(1444378334, 1),
                        "electionDate" : ISODate("2015-10-09T08:12:14Z"),
                        "configVersion" : 3,
                        "self" : true
                },
                {
                        "_id" : 2,
                        "name" : "45.63.50.67: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-10-09T11:28:27.754Z"),
                        "lastHeartbeatRecv" : ISODate("2015-10-06T08:52:51.239Z"),
                        "pingMs" : 406,
                        "lastHeartbeatMessage" : "Failed attempt to connect to 45.63.50.67:27017; couldn't connect to server 45.63.50.67:27017 (45.63.50.67), connection attempt failed",
                        "configVersion" : -1
                },
                {
                        "_id" : 3,
                        "name" : "43.241.222.110:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 90994,
                        "optime" : Timestamp(1444378212, 1),
                        "optimeDate" : ISODate("2015-10-09T08:10:12Z"),
                        "lastHeartbeat" : ISODate("2015-10-09T11:28:27.532Z"),
                        "lastHeartbeatRecv" : ISODate("2015-10-09T11:28:27.299Z"),
                        "pingMs" : 15,
                        "configVersion" : 3
                }
        ],
        "ok" : 1
}

CoamReSet:PRIMARY> config = rs.conf()
{
        "_id" : "CoamReSet",
        "version" : 3,
        "members" : [
                {
                        "_id" : 1,
                        "host" : "42.96.194.60:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : 0,
                        "votes" : 1
                },
                {
                        "_id" : 2,
                        "host" : "45.63.50.67:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : 0,
                        "votes" : 1
                },
                {
                        "_id" : 3,
                        "host" : "43.241.222.110:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : 0,
                        "votes" : 1
                }
        ],
        "settings" : {
                "chainingAllowed" : true,
                "heartbeatTimeoutSecs" : 10,
                "getLastErrorModes" : {

                },
                "getLastErrorDefaults" : {
                        "w" : 1,
                        "wtimeout" : 0
                }
        }
}

设置第一个节点 42.96.194.60 优先级为1,第二个节点 45.63.50.67 优先级为0,第三个节点 43.241.222.110 优先级为2;

CoamReSet:PRIMARY> config.members[0].priority = 1
1
CoamReSet:PRIMARY> config.members[1].priority = 0
0
CoamReSet:PRIMARY> config.members[2].priority = 2
2
CoamReSet:PRIMARY> rs.reconfig(config)
{ "ok" : 1 }
CoamReSet:PRIMARY> rs.status()
{
        "set" : "CoamReSet",
        "date" : ISODate("2015-10-09T12:03:37.679Z"),
        "myState" : 2,
        "syncingTo" : "43.241.222.110:27017",
        "members" : [
                {
                        "_id" : 1,
                        "name" : "42.96.194.60:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 616679,
                        "optime" : Timestamp(1444392119, 1),
                        "optimeDate" : ISODate("2015-10-09T12:01:59Z"),
                        "syncingTo" : "43.241.222.110:27017",
                        "configVersion" : 5,
                        "self" : true
                },
                {
                        "_id" : 2,
                        "name" : "45.63.50.67: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-10-09T12:03:35.875Z"),
                        "lastHeartbeatRecv" : ISODate("2015-10-06T08:52:51.239Z"),
                        "pingMs" : 406,
                        "lastHeartbeatMessage" : "Failed attempt to connect to 45.63.50.67:27017; couldn't connect to server 45.63.50.67:27017 (45.63.50.67), connection attempt failed",
                        "configVersion" : -1
                },
                {
                        "_id" : 3,
                        "name" : "43.241.222.110:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 93103,
                        "optime" : Timestamp(1444392119, 1),
                        "optimeDate" : ISODate("2015-10-09T12:01:59Z"),
                        "lastHeartbeat" : ISODate("2015-10-09T12:03:35.817Z"),
                        "lastHeartbeatRecv" : ISODate("2015-10-09T12:03:36.764Z"),
                        "pingMs" : 17,
                        "electionTime" : Timestamp(1444390463, 1),
                        "electionDate" : ISODate("2015-10-09T11:34:23Z"),
                        "configVersion" : 5
                }
        ],
        "ok" : 1
}

可以看到 43.241.222.110 已经成功切换成主节点了
关闭主节点 43.241.222.110 后,发现两个从节点没有自动切换成主节点,相当于关闭了 MongoDB 复制集功能
MongoDB RS优先级设置
http://docs.mongodb.org/manual/tutorial/force-member-to-be-primary/


问题解决

主节点 43.241.222.110 服务意外停止后,在从节点 42.96.194.60 修改优先级出现如下错误

1
2
3
4
5
6
7
8
9
10
CoamReSet:RECOVERING> config = rs.conf();
CoamReSet:RECOVERING> config.members[2].priority = 0;
CoamReSet:RECOVERING> rs.reconfig(config);
{
"ok" : 0,
"errmsg" : "replSetReconfig should only be run on PRIMARY, but my state is RECOVERING; use the \"force\" argument to override",
"code" : 10107
}
CoamReSet:RECOVERING> rs.reconfig(config,{force: true});
{ "ok" : 1 }

参考列表

高可用的MongoDB集群
MongoDB Replica Set 详细安装文档
rs.reconfig()

文章目录
  1. 1. MongoDB 复制集
    1. 1.1. 输出
    2. 1.2. 初始化副本集配置
    3. 1.3. 输出成功
    4. 1.4. 注意:新创建副本集必须要数据库没有数据,否则初始化会提示以下错误:
    5. 1.5. 先往 Primary 节点(43.241.222.110)插入数据,在 42.96.194.60 和 45.63.50.67 两台 Secondary 节点中查询数据,验证是否能够正常的同步机器.
  2. 2. 动态添加节点,删除节点.
  3. 3. 复制集优先级问题
  4. 4. 问题解决
  5. 5. 参考列表