上面的介绍的数据同步(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记录在前面复制集概述中已经描述过,关于复制集中节点权限配置的问题可在复制集启动的时候进行设置,也可以在启动后重新配置,这里先略过这一点,集中精力讨论故障转移。

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

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

先分析第一种情况的测试,当前复制集的配置情况如下:

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

{

"_id" : "rs0",

"version" : 3,

"members" : [

{

"_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命令知道哪些写操作成功了,哪些失败,驱动程序会返回失败的信息给应用程序,针对这个异常信息,应用程序可以决定怎样处置这个写操作,可以重新执行写操作,也可以直接给用户暴出这个错误。

mongoDB研究笔记:复制集故障转移机制的更多相关文章

  1. Mongodb 基础 复制集原理和搭建

    数据复制原理 开启复制集后,主节点会在local库下生成一个集合叫 oplog.rs,这是一个有限的集合,即大小固定.这个集合记入了整个mongod实例一段时间内数据库的所有变更操作(如:增/删/改) ...

  2. 关于MongoDb Replica Set的故障转移集群——理论篇

    自从10 gen用Replica Set取代Master/Slave方案后生活其实已经容易多了,但是真正实施起来还是会发现各种各样的小问题,如果不小心一样会栽跟头. 在跟Replica Set血拼几天 ...

  3. redis集群复制和故障转移

    #### 一.集群的问题- 1.当某个主节点宕机后,对应的槽位没有节点承担,整个集群处于失败状态,不可用,怎么办- 2.如何判断某个主节点是否真正的岩机?- 3.如果从某个主节点的所有从节点中选举出一 ...

  4. MongoDB之 复制集搭建

    MongoDB复制集搭建步骤,本次搭建使用3台机器,一个是主节点,一个是从节点,一个是仲裁者. 主节点负责与前台客户端进行数据读写交互,从节点只负责容灾,构建高可用,冗余备份.仲裁者的作用是当主节点宕 ...

  5. MongoDB 主从复制及 自动故障转移

    1.MongoDB 主从复制 MongoDB复制是将数据同步在多个服务器的过程. 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性. 复制还允许您从 ...

  6. mongodb之 复制集维护小结

    原文地址:https://www.cnblogs.com/zhaowenzhong/p/5667312.html 一.新增副本集成员 1.登录primary 2.use admin >rs.ad ...

  7. Kafka主题体系架构-复制、故障转移和并行处理

    本文讨论了Kafka主题的体系架构,讨论了如何将分区用于故障转移和并行处理. Kafka主题,日志和分区 Kafka将主题存储在日志中.主题日志分为多个分区.Kafka将日志的分区分布在多个服务器或磁 ...

  8. mongodb配置复制集replset

    Mongodb的replication主要有两种:主从和副本集(replica set).主从的原理和mysql类似,主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己 ...

  9. MongoDB 部署复制集(副本集)

    部署MongoDB复制集(副本集)   环境 操作系统:Ubuntu 18.04 MongoDB: 4.0.3 服务器 首先部署3台服务器,1台主节点 + 2台从节点 3台服务器的内容ip分别是: 1 ...

随机推荐

  1. 提高SQL查询效率(SQL优化)

    要提高SQL查询效率where语句条件的先后次序应如何写 http://blog.csdn.net/sforiz/article/details/5345359   我们要做到不但会写SQL,还要做到 ...

  2. 我的Windows软件清单

    1.evernote : 没错,这篇笔记就是用 evernote 写的,说实话,这款产品我只是在PC上用,虽然手机上也下了,不过似乎体验不是很好(可能是屏幕不够大的原因),用得非常少.这个软件里面可以 ...

  3. Android框架之AndroidAnnotations实战

    方案一: 下载 androidannotations-bundle-3.3.2.zip 方案二:   楼主选用开发环境:android studio 新建项目  修改app 下的build.gradl ...

  4. myeclipse安装flex插件后代码无自动提示及自动补全无效的解决办法

    在myeclipse配置flex插件后,可能会产生快捷键的冲突,或者快捷键设置被修改的情况,本文探索其解决办法 在卸载flex插件后,myeclipse的快捷键设置并不会自动还原,这需要我们手动设置. ...

  5. SVN版本控制系统

    SVN 版本控制系统 1.SVN作用 防止代码丢失 : 因为没有哪个项目能够一次性开发完成 代码版本回退 : 你可以在开发过程中找到以前上传到服务器上面的所有版本 多人代码整合 : 公司中多个人开发同 ...

  6. 安卓奇葩问题之:运行OK,打包安装崩溃(原因是:代码不规范导致编译出错)

    咳咳,还是那句话,真是日了狗了 这个问题真的很难找,废话不多少,上酸菜. 报错信息是这个方法返回的图片找不到 public static int getImgID(boolean isBig, int ...

  7. Linux图片批处理

    通过imagemagick的convert命令来处理. 将多个图片横向拼接(宽图): convert +append 1.jpg 2.jpg all.jpg #人为指定顺序 convert +appe ...

  8. elasticsearch-查询

    使用如下语句创建一个名字为:user_document,别名为user的索引 PUT:http://localhost:9200/user_document { "settings" ...

  9. nginx日常运维

    pid丢失办法: 1.查找nginx进程ID ps -ef | grep nginx 2.将进程ID写入pid > /tmp/nginx.pid 3.重启nginx

  10. Python 类的命名空间

    Python中类的定义其实就是执行代码块: class cc: a=0 print '+++++', print a 会直接执行print语句而不是在实例化cc时执行.执行后会生成对应的类的命名空间. ...