mongoDB研究笔记:复制集故障转移机制

上面的介绍的数据同步(http://www.cnblogs.com/guoyuanwei/p/3293668.html)至关于传统数据库中的备份策略,mongoDB在此基础还有自动故障转移的功能。在复制集概述那一节提到过心跳"lastHeartbeat"字段,mongoDB就是靠它来实现自动故障转移的。 mongod实例每隔2秒就向其它成员发送一个心跳包以及经过rs.staus()中返回的成员的”health”值来判断成员的状态。若是出现复制集中primary节点不可用了,那么复制集中全部secondary的节点就会触发一次选举操做,选出一个新的primary节点。如上所配置的复制集中若是primary节点宕机了,那么就会选举secondary节点成为primary节点,arbiter节点只是参与选举其它成员成为primary节点,本身永远不会成为primary节点。若是secondary节点有多个则会选择拥有最新时间截的oplog记录或较高权限的节点成为primary节点。oplog记录在前面复制集概述中已经描述过,关于复制集中节点权限配置的问题可在复制集启动的时候进行设置,也能够在启动后从新配置,这里先略过这一点,集中精力讨论故障转移。html

若是是某个secondary节点失败了,只要复制集中还有其它secondary节点或arbiter节点存在,就不会发生从新选举primary节点的过程。mongodb

下面模拟两种失败场景:一是secondary节点的失败,而后过一段时间后重启(时间不能无限期,不然会致使oplog.rs集合严重滞后的问题,须要手动才能同步);二是primary节点失败,故障转移发生。数据库

先分析第一种状况的测试,当前复制集的配置状况以下:编程

(1)rs0:PRIMARY> rs.conf()安全

{socket

"_id" : "rs0",编程语言

"version" : 3,测试

"members" : [ui

{htm

"_id" : 0,

"host" : "Guo:40000" //primary节点

},

{

"_id" : 1,

"host" : "Guo:40001" //secondary节点

},

{

"_id" : 2,

"host" : "Guo:40002", //arbiter节点

"arbiterOnly" : true

}

]

}

(2)经过Kill掉secondary节点所在的mongod实例,经过rs.status()命令查看复制集状态,secondary节点状态信息以下:

"_id" : 1,

"name" : "Guo:40001",

"health" : 0,

"state" : 8, //表示成员已经down机

"stateStr" : "(not reachable/healthy)",

"uptime" : 0,

"optime" : {

"t" : 1376838296,

"i" : 1

},

"optimeDate" : ISODate("2013-08-18T15:04:56Z")

(3)接着经过primary节点插入一条记录:

rs0:PRIMARY> db.scores.insert({stuid:2,subject:"english",score:100})

(4)再次查看复制集状态信息rs.status(),能够看到primary成员节点上oplpog信息以下:

"optime" : {

"t" : 1376922730,

"i" : 1

},

"optimeDate" : ISODate("2013-08-19T14:32:10Z"),

与上面down机的成员节点比较,optime已经不同,primary节点上要新于down机的节点。

(5)从新启动Kill掉的节点

>mongod --config E:\mongodb-win32-i386-2.4.3\configs_rs0\rs0_1.conf

查询复制集状态信息rs.status(),观看节点"Guo:40001"的状态信息以下:

"_id" : 1,

"name" : "GUO:40001",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 136,

"optime" : {

"t" : 1376922730, //与上面primary节点一致了

"i" : 1

},

"optimeDate" : ISODate("2013-08-19T14:32:10Z"),

说明secondary节点已经恢复,而且从primary节点同步到了最新的操做数据。进一步经过查询secondary节点上local数据库上的oplog.rs集合来进行验证,发现多了一条下面这样的记录:

{ "ts" : { "t" : 1376922730, "i" : 1 }, "h" : NumberLong("-451684574732211704"),

"v" : 2, "op" : "i", "ns" : "students.scores", "o" : { "_id" : ObjectId("52122c

6a99c5a3ae472a6900"), "stuid" : 2, "subject" : "english", "score" : 100 } }

这正是在primary节点上插入的记录,再次证实数据确实同步过来了。

接下来测试第二种状况:

(1)将primary节点Kill掉。

查询复制集的状态信息rs.status()

"name" : "Guo:40000",

"health" : 0,

"state" : 8,

"stateStr" : "(not reachable/healthy)"

字段"health"的值为0,说明原来的primary节点已经down机了。

"name" : "Guo:40001",

"health" : 1,

"state" : 1,

"stateStr" : "PRIMARY"

字段"stateStr"值为"PRIMARY",说明原来secondary节点变成了primary节点。

(2)在新的primary节点上插入一条记录

rs0:PRIMARY> db.scores.insert({stuid:3,subject:"computer",score:99})

(3)从新恢复"Guo:40000"节点(原来的primary节点)

>mongod --config E:\mongodb-win32-i386-2.4.3\configs_rs0\rs0_0.conf

再次查看复制集状态rs.status()

"name" : "Guo:40000",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 33,

"optime" : {

"t" : 1376924110,

"i" : 1

},

当"Guo:40000"实例被从新激活后,变成了secondary节点,oplog也被同步成最新的了。说明当primary节点故障时,复制集能自动转移故障,将其中一个secondary节点变为primary节点,读写操做继续在新的primary节点上进行。原来primary节点恢复后,在复制集中变成了secondary节点。

上面两中状况都获得了验证,可是有一点要注意,mongDB默认状况下只能在primary节点上进行读写操做。对于客户端应用程序来讲,对复制集的读写操做是透明的,默认状况它老是在primary节点上进行。 mongoDB提供了不少种常见编程语言的驱动程序,驱动程序位于应用程序与mongod实例之间,应用程发起与复制集的链接,驱动程序自动选择primary节点。当primary节点失效,复制集发生故障转移时,复制集将先关闭与全部客户端的socket链接,驱动程序将返回一个异常,应用程序收到这个异常,这个时候须要应用程序开发人员去处理这些异常,同时驱动程序会尝试从新与primary节点创建链接(这个动做对应用程序来讲是透明的)。假如这个时候正在发生一个读操做,在异常处理中你能够从新发起读数据命令,由于读操做不会改变数据库的数据;假如这个时候发生的是写操做,状况就变得微妙起来,若是是非安全模式下的写,就会产生不肯定因素,写是否成功不肯定,若是是安全模式,驱动程序会经过getlasterror命令知道哪些写操做成功了,哪些失败,驱动程序会返回失败的信息给应用程序,针对这个异常信息,应用程序能够决定怎样处置这个写操做,能够从新执行写操做,也能够直接给用户暴出这个错误。

相关文章
相关标签/搜索