关于MongoDb Replica Set的故障转移集群——实战篇

如果你还不了解Replica Set的相关理论,请猛戳传送门阅读笔者的上一篇博文。

因为Replica Set已经属于MongoDb的进阶应用,下文中关于MongoDb的基础知识笔者就不再赘述了,请参考MongoDb Manual

下面分各种场景讲述如何创建一个Replica Set。

Standalone到Replica Set

这是相对简单的一种情况。如果你刚刚在生产环境应用MongoDb,很有可能适用于这种场景。

一台独立的MongoDb实例变为Replica Set的首位成员很容易,需要两个步骤:

1. 运行参数中加入--replicaSet <set name>。如:

mongod --dbpath /var/lib/mongo/ --replicaSet rs0 --fork

如果开启了认证模式则需要额外的一步:为实例配置一个Key,作为今后不同实例间认证的根据。

Key的原理很简单,只要不同实例拥有相同的Key,则认证成功。没有公私钥交换等等麻烦的过程。

生成Key也很简单,任何一个文件存了字符串都可以成为Key。只要保证不同实例使用相同的Key文件即可。

添加Key请使用参数 --keyFile=<file path>。生成Key请参考官方文档

2. 进入MongoDb命令行进行初始化,大致情况如下:

$ mongo localhost:27011
MongoDB shell version: 2.4.9
connecting to: localhost:27011/test
> rs.initiate()
{
    "info2" : "no configuration explicitly specified -- making one",
    "me" : "YX-ARCH:27011",
    "info" : "Config now saved locally.  Should come online in about a minute.",
    "ok" : 1
}

稍等片刻,集群初始化完成,回车后提示符从">"变为

rs0:PRIMARY> 

表示该实例已经成为一个Primary结点。此时集群中只有一个结点,不存在投票问题,所以无论怎么折腾这个结点都会保持Primary状态。但到下一步就要小心了。

rs0:PRIMARY> rs.add("YX-ARCH:27012")
{ "ok" : 1 }

此时第二个结点YX-ARCH:27012已加入集群,可以使用以下命令查看集群状态:

rs0:PRIMARY> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2014-01-24T07:21:01Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 0,
            "name" : "YX-ARCH:27011",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 353,
            "optime" : Timestamp(1390548012, 1),
            "optimeDate" : ISODate("2014-01-24T07:20:12Z"),
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "YX-ARCH:27012",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 49,
            "optime" : Timestamp(1390548012, 1),
            "optimeDate" : ISODate("2014-01-24T07:20:12Z"),
            "lastHeartbeat" : ISODate("2014-01-24T07:21:00Z"),
            "lastHeartbeatRecv" : ISODate("2014-01-24T07:21:00Z"),
            "pingMs" : 0,
            "syncingTo" : "YX-ARCH:27011"
        }
    ],
    "ok" : 1
}

可见27011此时是Primary身份,而27012则是Secondary身份。如果想改变结点的角色,则需要修改集群的配置。首先将集群配置调出:

rs0:PRIMARY> conf = rs.conf()
{
    "_id" : "rs0",
    "version" : 2,
    "members" : [
        {
            "_id" : 0,
            "host" : "YX-ARCH:27011"
        },
        {
            "_id" : 1,
            "host" : "YX-ARCH:27012"
        }
    ]
}

上篇讲过每个集群结点都有一个priority属性,默认为1。要改变一个实例的角色,我们只需要给新的实例设置一个高于当前Primary的priority就可以实现了。

注意因为只有Primary结点是可写的,所以重新配置群集的操作只能在Primary结点上进行。

rs0:PRIMARY> conf.members[1].priority = 2
2
rs0:PRIMARY> rs.reconfig(conf)
Fri Jan 24 15:25:36.069 DBClientCursor::init call() failed
Fri Jan 24 15:25:36.070 trying reconnect to localhost:27011
Fri Jan 24 15:25:36.070 reconnect localhost:27011 ok
reconnected to server after rs command (which is normal)

rs0:SECONDARY>

可见短暂的罢工后命令行自动重新连接到当前实例,但从提示符可以看出,当前实例已经变为Secondary角色。我们来随便逛逛Secondary里面的内容(Test是笔者自己建立的库)

rs0:SECONDARY> show dbs
Test    0.203125GB
local    2.0771484375GB
rs0:SECONDARY> use Test
switched to db Test
rs0:SECONDARY> show collections
Fri Jan 24 15:28:32.697 error: { "$err" : "not master and slaveOk=false", "code" : 13435 } at src/mongo/shell/query.js:128

如果用过Master Slave集群的读者应该发现了,Slave结点是可读的,而Secondary结点默认却不可读。要解决这个问题,只需要简单的一步:

rs0:SECONDARY> rs.slaveOk()
rs0:SECONDARY> show collections
system.indexes
test

至此一个拥有2个实例的MongoDb Replica Set就建立完成了。那么我们来试试传说中的故障恢复特性。

假设Primary结点因故停止工作了(我们手动干掉它)

$ ps awx | grep mongo
12546 ?        Sl     0:08 mongod --config mongodb1.conf
14201 ?        Sl     0:07 mongod --config mongodb2.conf  <--Primary在这
20258 pts/2    Sl+    0:00 mongo localhost:27012
24186 pts/0    S+     0:00 grep --color=auto mongo
$ kill 14201

在美好的幻想中,Secondary应该马上即位成为新的Primary吧?

$ mongo localhost:27011
MongoDB shell version: 2.4.9
connecting to: localhost:27011/test
rs0:SECONDARY> 

神马?还是Secondary?说好的故障恢复呢?

或许是姿势不对?那我们重新启动两个实例,这回先当掉Secondary试试

$ ps awx | grep mongo
12546 ?        Sl     0:10 mongod --config mongodb1.conf  <-- Secondary在这
20258 pts/2    Sl+    0:00 mongo localhost:27012
27024 ?        Sl     0:00 mongod --config mongodb2.conf
27413 pts/0    S+     0:00 grep --color=auto mongo
$ kill 12546
$ mongo localhost:27012
MongoDB shell version: 2.4.9
connecting to: YX-ARCH:27012/test
rs0:SECONDARY> 

神马?Primary降级为Secondary了?如果没看上篇的读者心里应该暗暗骂娘了吧?”禽兽,这算什么错误恢复集群?明明就是两个都死了!“

那么我们再把死掉那个Secondary复活试试?你会发现Primary又回来了。上篇说过,提升到Primary是一个很严格的过程,一旦出现2个Primary的情况,集群就废了。所以宁可错杀1000也不可放过一个。

所以实际发生的事情是这样的:当集群中仅有的2个实例挂掉一个,剩下的一个并不能判断自己的存活状况,因为也可能是自己跟网络断开了连接造成的。另外一个实例说不定还活得好好的呢。因此没有办法,暂时让自己成为Secondary活下去吧。

一旦另外一个实例恢复生存,两个实例就可以互相证明对方存活,因此还是priority较高的那个继续扮演Primary。

为了避免这种悲剧的发生,Arbiter的必要性就体现出来了。

自然你可以在群集中再加一个Secondary,让三个实例互相证明存活性,这样不仅刚才的问题可以解决 ,自动切换也是可以达成的。但是要成为Secondary的服务器可是对性能有一定要求的,现实情况下这样做可能性价比并不高。那么还是添加一个Arbiter吧,它的存在只是为了投票选举,不占用额外资源,放在资源有限的虚拟机中就足够了。如果有多个Arbiter为不同的集群服务,也可以放进同一台虚拟机中以节省资源。

rs0:PRIMARY> rs.addArb("YX-ARCH:27013")
{ "ok" : 1 }

顺带一提,刚才我们的操作中一直使用的是我的机器名"YX-ARCH",而不是localhost。这里localhost是被禁止使用的,原因是这样:

如果在命令行查看集群信息

rs0:PRIMARY> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2014-01-24T08:08:32Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 0,
            "name" : "YX-ARCH:27011",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 1010,
            "optime" : Timestamp(1390550842, 1),
            "optimeDate" : ISODate("2014-01-24T08:07:22Z"),
            "lastHeartbeat" : ISODate("2014-01-24T08:08:30Z"),
            "lastHeartbeatRecv" : ISODate("2014-01-24T08:08:32Z"),
            "pingMs" : 0,
            "syncingTo" : "YX-ARCH:27012"
        },
        {
            "_id" : 1,
            "name" : "YX-ARCH:27012",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 1758,
            "optime" : Timestamp(1390550842, 1),
            "optimeDate" : ISODate("2014-01-24T08:07:22Z"),
            "self" : true
        },
        {
            "_id" : 2,
            "name" : "YX-ARCH:27013",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",
            "uptime" : 70,
            "lastHeartbeat" : ISODate("2014-01-24T08:08:31Z"),
            "lastHeartbeatRecv" : ISODate("2014-01-24T08:08:32Z"),
            "pingMs" : 0
        }
    ],
    "ok" : 1
}

我们可以看到集群中有三个实例,分别是

YX-ARCH:27011
YX-ARCH:27012
YX-ARCH:27013

当使用某种语言,比如C#来连接MongoDb的时候,哪些服务器可用的信息并不是从连接字符串中来的,而是Driver会得到一份类似以上的信息来判断哪些服务器可用。可见,如果添加到集群中的地址是localhost:27011,那么Driver也会认为localhost:27011是一台可用的实例。但多数情况下应用和数据库都是分开的,这会造成应用徒劳地从自己机器上的27011端口去找MongoDb服务,显然是不可能成功的。关于获取可用实例的问题,笔者之前写过一篇日志,请戳传送门

以上已经建立了一个完整的集群,望大家用得开心。但作为摸爬滚打了多年的IT人,我是万万不敢在没有考虑后路的情况下就往生产环境上使用一个自己不知根知底的系统的。进兵前先考虑退路是常识,所以还是要考虑一下万一的情况下,如何从Replica Set退回Standalone的场景。

Replica Set 到 Standalone

考虑上述3个实例的Replica Set,它虽然可以在任何一个实例当掉的情况下保持正常工作,那如果2个实例同时当掉呢?什么,不可能有这么衰?前人的经验告诉我们:在IT的世界里,只要有可能发生的事情就一定会发生

所以当灾难来临的时候如果你两手空空,怎么能不被打个鼻青脸肿?那么,操家伙开干。

无论Primary还是Secondary,只要去掉--replicaSet即可马上变回Standalone的状态。如果要彻底回到Standalone状态,还应该删除数据库目录下的local.*文件(注意删除操作必须在MongoDb停止服务的情况下进行)。

如果不删这些文件,MongoDb也会正常工作,但TTL Collection会工作不正常。此外笔者还没发现有什么问题。

现实是,在多数情况下我们是不会希望从Replica Set变回Standalone的。如果你真的这么做了,那大概只有一个原因:踩了上文中的某个雷,导致集群变成完全只读的了。你期望暂时变回Standalone状态,以便不影响生产环境的日常操作,等其他的实例恢复之后再加上--replicaSet参数变回Replica Set状态。很不幸,如果你是这个目的,那么你马上会踩第二个雷。

我们知道Replica Set的原理是传送oplog并重做,而oplog只有在master/slave或replica set模式下才会生成。所以当你回到standalone模式下时所做的任何事情都是没有oplog的,这意味着当你再次回到Replica Set模式中时会丢失部分数据。

更气人的是:MongoDb不会阻止你做这样的事情,它会让你成功回到Replica Set状态。无论是Primary还是Secondary都可以。你甚至可以在Secondary变成Standalone期间修改它的内容后再让它回到ReplicaSet,这样它的内容就跟其他实例不一致!

知道这个坑之后来看看简单粗暴的解决办法:

1. 停止MongoDb实例

$ sudo systemctl stop mongodb

2. 进入数据库文件夹删除local.*

$ cd /var/lib/mongodb/
$ rm local.* -rf

3. 把--replicaSet参数重新添加回配置文件

4. 重启启动MongoDb

sudo systemctl start mongodb

此时MongoDb变回普通的非Replica Set实例

5. 按上文的方法重新初始化Replica Set并建立集群。

虽然复杂了点,但这也是没有办法的事情,千万不可走捷径。

Master/Slave到Replica Set

Master/Slave到Replica Set其实和Standalone到Replica Set并无两样,所有步骤完全相同。要注意的只有一点,一旦Master变成Primary,Slave将不再从它同步数据。也就是说从执行

> rs.initiate()

的一刻开始,Slave就成为了当时数据库的快照,不再更新。所以在生产环境中应用这个操作时,要注意数据不同步可能带来的危害,必要时必须停机维护。遇到这类问题时:

方案一:可以把原来使用Slave的应用切换为使用Master,优点是可以全程不间断服务。缺点是要求你的Master性能足够好。

方案二:如果想使用方案一但Master的性能又不够好,可以使用一台足够强大的新机器先做为Slave,然后所有系统停机维护,这时把Slave变为Master,所有服务使用新的Master继续工作。之后再从这台Master开始向Replica Set的转换工作。优点是停机时间可以比较短。缺点嘛……服务中断了……另外所有系统指向新的Master时视系统规模可能修改比较多,容易有疏漏。

方案三:完全停机进行master/slave到replica set的转换。所有Secondary完成复制后再开始重新服务。这当然是最轻松的方案了,自然停机时间也是最长的。

后记

MongoDb作为新兴的非关系型数据库近年来发展迅速。新特性层出不穷。想了解它的方方面面,最简单的方法是读它的User manual。虽然是件费力的事情,但也是没有办法的事情,就像上面提到的一样,想走捷径的结果往往是掉进坑里。

希望笔者的血泪史为小伙伴们提供前车之鉴,本文如有不正确之处欢迎指正。

转载于:https://www.cnblogs.com/yaoxing/p/mongodb-replica-set-setup.html

【水下小目标检测】SWIPENet与样本重加权:应对模糊与噪声的深度学习策略 本文深入探讨了水下小目标检测的挑战与解决方案,重点介绍了SWIPENet网络架构与IMA样本重加权算法。通过空洞卷积模块、特征金字塔重构和多尺度预测机制,SWIPENet有效提升了模糊目标的检测精度。结合Invert Multi-Class Adaboost算法,系统性地解决了水下环境中的样本不均衡问题,在URPC数据集上实现了48.8%的mAP,特别适合海洋生物检测等应用场景。 阅读详情

相关推荐

从零到一:i.MX8M Plus开发板全流程开发指南(源码编译、烧录、镜像运行)

本文详细介绍了i.MX8M Plus开发板的全流程开发指南,包括源码编译、烧录和镜像运行等关键步骤。通过实战案例和配置技巧,帮助开发者快速掌握工业级应用开发,提升在边缘计算和AI推理等领域的开发效率。

weixin_30687051的博客 551

docker使用 docker-compose 部署MongoDB4.0 部署replica set(副本集)集群

docker使用 docker-compose 部署MongoDB4.0 部署replica set(副本集)集群

HelloBiu的博客 7382

Open3D——直通滤波(python详细过程版)【2025最新版】

python就一个字:强。博客长期更新,本文最近更新时间为:2025年1月11日。

点云侠的博客 7489

Mongo Replica Set(未完)

1. Replica Set(复制集) 官方连接 1.0 定义 多个维护了同一个数据集合的 mongod 进程(可以单服务器),它们为系统提供两天冗余和高可用。 A replica set in MongoDB is a group of mongod processes that maintain the same data set 1.1 Replica Set Members Primary(主节点):接收所有的写操作 Secondaries(从节点):为了与主节点的数据集相同,会复制主节点上的写操作

C573751767的博客 1195

mongodb集群搭建-replica set模式

1 前提: 原来有个节点169,已经搭建了mongodb,现在想再增加两个节点167和168做repliset模式的mongo集群, 其中167做为协调节点,168作为副节点,169作为主节点 2 配置 在原来169配置文件的基础上,增加一个配置:replSet=mongotest 原配置: dbpath=/opt/mongodb-3.0.6/db logpath=/opt/mo

快乐的瑾 874

MongoDB replication (1)

MongoDB replication (1)> rs.initiate() { "ok" : 0, "errmsg" : "This node was not started with the replSet option", "code" : 76, "codeName" : "NoReplicationEnabled" }启动时没有配置复制集,使用mongo –

Aegeaner的专栏 7733

mongodb搭建Replica Set

1.创建数据文件夹: mkdir -p /data/master mkdir -p /data/slaver mkdir -p /data/arbiter 效果: data 文件夹包含 arbiter master slaver 三个文件夹 2.创建日志存放文件 vi /log/master.log vi /log/slaver.log vi /log/arbiter.log 效果: log文件夹包含 master.log slaver.log ar...

一起学习一起进步~ 1581

[MongoDB] 安装MongoDB配置Replica Set

MongoDB的环境主要包括StandAlone,Replication和Sharding。 StandAlone:单机环境,一般开发测试的时候用。Replication:主从结构,一个Primary,多个Secondary,可能会有Arbitry。 Primary挂掉之后,会选举出一个Secondary作为Primary,与zookeeper类似。Arbitry上面不存数据,只是为了

隐之狐的专栏 1668

Mongodb Replica Sets 副本集群搭建

通过oplog日志进行添加节点操作简单,但oplog是capped collection,采用循环的方式处理日志,通过oplog日志来添加节点,可能导致数据的不一致(日志被刷新),因此我们引出快照和oplog相结合的方式来添加节点,保证数据的一致性。Sharding 模式适合处理大量数据,它将数据分开存储,不同服务器保存不同的数据,所有服务器数据的总和即为整个数据集。它的核心作用是数据的备份和故障转移。方式:复制一份副本集的物理文件来做初始化数据,然后使用oplog日志来追溯数据,最终达到数据的一致性。

zll4859291的博客 1482

MongoDB 高可用部署:Replica Set 搭建与故障转移测试

MongoDB 高可用部署:Replica Set 搭建与故障转移测试。在分布式系统设计中,高可用性(High Availability,HA)是一个核心的质量属性,它衡量系统提供服务的时间比例。MongoDB 通过副本集(Replica Set)机制实现高可用性,其设计基于以下几个关键理论: CAP 定理的应用: MongoDB 副本集在 CAP 定理中主要提供CP(一致性和分区容错性) 特性。在网络分区发生时,系统优先保证数据一致性,可能会暂时牺牲部分可用性。这种设计选择确保了数据的正确性,避免了脑裂情

夜雨的博客 1277

mongodb Replica Set集群搭建(三节点)

MongoDB三节点Replica Set集群搭建摘要 本文详细介绍了MongoDB三节点副本集的搭建过程。三个节点IP分别为192.168.56.107、192.168.56.113和192.168.56.114。搭建步骤包括:准备软件包、创建数据目录、配置各节点mongodb.cfg文件(指定不同端口和角色)、启动MongoDB服务。通过mongosh连接到主节点后,使用rs.initiate()初始化集群配置,其中192.168.56.107设为主节点(priority=2),192.168.56.1

Mrzhou的博客 542

MongoDB Replica-set 设置

MongoDB Replica-set 设置

fduffyyg的博客 4155

Mongodb Replica Set + Sharding集群

1.  配置副本集 1)、启动各mongod节点 mkdir -p /var/store/mongodb/{shard11,shard12,shard13,shard21,shard22,shard23} mkdir -p /var/log/mongodb/ sudo chmod 777 -R /var/store/mongdb sudo chmod 77

niao_ye 678

mongodb Replica Set (复制集)

mongodb主从复制搭建以及常用操作,超级详细

a142151的博客 1179

MongoDB(9)什么是MongoDB的副本集(Replica Set)?

MongoDB副本集通过多节点数据复制实现高可用性和数据冗余,包含主节点(Primary)和副本节点(Secondary)。主节点处理写操作,副本节点同步数据并支持读扩展。当主节点故障时,副本集自动选举新主节点,保障服务连续性。配置步骤包括:1)启动多个MongoDB实例;2)初始化副本集;3)通过应用程序连接副本集进行读写操作。副本集还支持仲裁节点(Arbiter)参与选举,确保集群拥有奇数成员。该机制有效提升了数据库的容灾能力和读取性能。

qq_43012298的博客 860

mongodb学习笔记—mongodb集群搭建(replica set集群

##集群规划 IP 端口 角色 10.1.200.77 27017 primary 10.1.200.78 27017 secondary 10.1.200.87 27017 secondary 10.1.200.118 27017 secondary repl...

chfantv17156的博客 511

MongoDB 副本集(Replica Set) 的工作机理

所有读都走主,能保证“读到你刚写的”(read-your-writes),一致性最好。典型默认:心跳约每 2s,选举超时 ~10s(不同版本/配置略有差异)。跨分片事务需分片集群支持(4.2+)。为了降低“从库过旧”的风险,可配。:多文档事务(在副本集内)需要走。限制从库最大允许滞后。:确认写入的“应答级别”

喝醉酒的小白 1570

Centos7搭建Mongodb replica set集群

Mongodb Replica Set集群简介 Mongodb ReplicaSet 集群由Primary,Secondary,Arbiter这3个角色组成,如下图所示: Primary:主节点,可读可写,负责数据的写入,并将数据同步复制到Secondary节点上 Secondary:从节点,只能提供数据的读取操作,当主节点异常时可以迅速切换为主节点。 Arbiter:观察者节点,负责投票选举出主节点。 这3类节点之间通过互相发送心跳包保持连接记录相互之间的状态。当主节点崩溃时,观察者节点负责投票选举出

715

(1)解锁MongoDB replica set核心姿势

本文倒腾目前大热的MongoDB Replica Set集群,在倒腾的同时串讲一些 MongoDB特性。副本集ReplicaSet是一个术语,定义具有多节点的数据库集群,这些节点具有主...

dotNET跨平台 247

mongodb集群搭建之Replica-Set方式

mongodb集群搭建有三种方式。 1、Master-Slave模式 2、Replica-Set方式 3、Sharding方式 其中,第一种方式基本没什么意义,官方也不推荐这种方式搭建。另外两种分别就是副本集和分片的方式。今天介绍副本集的方式搭建mongodb高可用集群。 副本集的方式也很容易理解,这里需要一个主节点,一个备节点,如果主节点发生故障,那么会启用备节点,当主节点修复之后,主节点再次

feinifi的博客 1万+

MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离

📝 MongoDB副本集与高可用性摘要 本文深入讲解了MongoDB副本集(Replica Set)的核心机制与应用: 1️⃣ 架构组成:主节点(Primary)处理写请求,从节点(Secondary)同步数据,仲裁节点(Arbiter)参与选举投票 2️⃣ 高可用原理:通过心跳检测(默认2秒)和自动选举机制(10秒超时)实现故障转移 3️⃣ 读写分离:支持primary/secondary/nearest等多种读偏好模式,优化查询性能 4️⃣ 关键运维:包含副本集搭建、状态监控(rs.status())

silverclayz的技术分享 944
上一篇: 线程的几种用法
下一篇: 使用 highchart 绘制柱状图的通用方法与接口
weixin_30699465
博客等级 码龄11年 102粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值