`

mongodb利用rs,实现ha和备份

 
阅读更多

mongodb最简单的部署方式,是单节点部署。国庆前找了台8核,48G RAM的server,在100+并发的压力下跑了一个星期,也没有发现数据丢失和server负载过大的情况


但是单节点部署还是有一些问题,第一是无法做HA,如果该mongod down掉,或者部署的server down掉,应用就无法工作;第二是不利于备份,因为在备份的时候,会给mongod额外的负担,有可能影响业务;第三是无法做读写分离。所以在生产环境下,依然考虑使用集群部署


mongod支持的集群部署方式有3种:

1、master-slave

2、replica set

3、sharding


master-slave可以解决备份的问题,但是无法透明地HA,所以也不大好;sharding是mongo的一个亮点特性,可以自动分片。但是根据我的测试结果,在单集合达到2000万条数据的门槛之后,sharding才开始体现出性能优势,而sharding的数据是分布式的,所以备份会比较复杂,而且也需要更多的服务器,不利于成本。所以最后我考虑,还是使用replica set方式的集群部署比较合适。可以解决HA,备份,读写分离的问题


基本上采用官网推荐的这种TOPO:


理想情况下,最好是3个mongod实例分别部署在单独的server上,这样就需要3台server;出于成本考虑,也可以把2台secondary部署在同一台server上,primary由于要处理读写请求(读写暂不分离),需要很多内存,并且考虑HA因素,所以primary是需要保证独占一台server比较好,这样就一共需要2台server


一、集群配置方式


1、以-replset方式启动mongod

也可以用命令行启动,但是不利于管理,所以建议采用--config参数来启动,配置文件如下:

port=2222
bind_ip=127.0.0.1
dbpath=/home/zhengshengdong/mongo_dbs/db1
fork=true
replSet=rs0
logpath=/home/zhengshengdong/mongo_log/log1.txt
logappend=true
journal=true

./mongod --config /home/zhengshengdong/mongo_confs/mongo1.conf

然后如法炮制,启动另外2个mongod实例

2、初始化replica set,并添加secondary

用./mongo --port 2222连上准备作为primary的mongod实例,然后依次执行以下命令

rs.initiate()
rs.conf()
rs.add("host1:port")
rs.add("host2:port")

3、检查

在primary实例上执行

rs.status()
应该能看到类似下图的效果


二、验证HA场景

用java driver写了以下代码来做验证

public static void main(String[] args) throws UnknownHostException {

		ScheduledExecutorService executor = Executors
				.newSingleThreadScheduledExecutor();

		final MongoClient client = MongoConnectionHelper.getClient();
		client.setWriteConcern(WriteConcern.REPLICA_ACKNOWLEDGED);

		Runnable task = new Runnable() {

			private int i = 0;

			@Override
			public void run() {
				DB db = client.getDB("yilos");
				DBCollection collection = db.getCollection("test");
				DBObject o = new BasicDBObject("name", "MongoDB" + i).append(
						"count", i);
				try {
					collection.insert(o);
				} catch (Exception exc) {
					exc.printStackTrace();
				}

				i++;
			}
		};

		executor.scheduleWithFixedDelay(task, 1, 1, TimeUnit.SECONDS);

	}
每隔1秒往集群中写入一条数据,然后手动把primary shutdown,观察发现jvm console给出提示:

警告: Primary switching from zhengshengdong-K43SA/127.0.0.1:2222 to mongodb.kyfxbl.net/127.0.0.1:4444

这条消息说明,mongo自动处理了primary的切换,对于应用来说是透明的。然后查看mongo中的记录,发现在切换完成以后,写入操作确实继续了


上图可以看到,在2926和2931之间,正在进行primary倒换,在完成之后,应用可以继续写入数据

但是明显可以看到,中间2927,2928,2929,2930这4条数据丢失了(mongo的primary倒换大约需要3-5秒时间),对于业务来说,虽然时间不长,但是如果因此丢失了业务数据,也是不能接受的

接下来再仔细看下这段时间内代码抛出的异常:

com.mongodb.MongoException$Network: Write operation to server mongodb.kyfxbl.net/127.0.0.1:4444 failed on database yilos
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:153)
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:115)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:248)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
at com.mongodb.DBCollection.insert(DBCollection.java:76)
at com.mongodb.DBCollection.insert(DBCollection.java:60)
at com.mongodb.DBCollection.insert(DBCollection.java:105)
at com.yilos.mongo.HATester$1.run(HATester.java:36)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at org.bson.io.PoolOutputBuffer.pipe(PoolOutputBuffer.java:129)
at com.mongodb.OutMessage.pipe(OutMessage.java:236)
at com.mongodb.DBPort.go(DBPort.java:133)
at com.mongodb.DBPort.go(DBPort.java:106)
at com.mongodb.DBPort.findOne(DBPort.java:162)
at com.mongodb.DBPort.runCommand(DBPort.java:170)
at com.mongodb.DBTCPConnector._checkWriteError(DBTCPConnector.java:100)
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:142)
... 16 more

可以发现,实际上这并不是mongo的问题,而是这段测试代码的BUG引发的:

Runnable task = new Runnable() {

			private int i = 0;

			@Override
			public void run() {
				DB db = client.getDB("yilos");
				DBCollection collection = db.getCollection("test");
				DBObject o = new BasicDBObject("name", "MongoDB" + i).append(
						"count", i);
				try {
					collection.insert(o);
				} catch (Exception exc) {
					exc.printStackTrace();
				}

				i++;
			}
		};
问题就出在这里,try语句中捕获到了MongoException,但是我写的这段代码并没有进行处理,只是简单地打印出异常,然后把i自增后,进入下一次循环。

从中也可以判断出,mongo提供的java driver,并不会把失败的write操作暂存在队列中,稍后重试;而是抛弃这次写操作,抛出异常让客户端自行处理。我觉得这个设计也是没问题的,但是客户端一定要进行处理才行。由于后续是使用js driver,所以对这段代码就不继续深究了,在js driver中再仔细研究。关键是要处理mongo exception,以及设置较高级别的write concern。replica set本身的HA机制是可行的

三、备份方案

采用2级备份:

第一层是集群部署提供的天然备份,由于存在2个secondary node,会和primary始终保持同步,因此在任何时候,集群都有2份完整的数据镜像副本

第二层则是使用mongo提供的mongodump和fsync工具,通过手工执行或者脚本的方式,在业务负载低(凌晨3点)的时候,获取关键collection的每日副本。备份采集也在secondary上执行,不给primary额外的压力

采集的备份,保存到本地或者其他的server,避免server的存储损坏,造成数据和备份全部丢失

同时,在启动mongod的时候,打开journal参数,这样在极端情况下(上述2种备份都失败),还可以通过oplog进行手工恢复

分享到:
评论

相关推荐

    mongodb 备份恢复工具

    mongodb 备份恢复工具mongodb 备份恢复工具mongodb 备份恢复工具mongodb 备份恢复工具mongodb 备份恢复工具mongodb 备份恢复工具mongodb 备份恢复工具mongodb 备份恢复工具mongodb 备份恢复工具mongodb 备份恢复工具...

    mongodb4.2全量定时增量备份python脚本

    本话题主要围绕"mongodb4.2全量定时增量备份python脚本"展开,讲解如何利用Python编写脚本来实现这一功能。 首先,全量备份是指对数据库进行一次完整的数据复制,不考虑任何历史状态。在MongoDB中,我们可以使用`...

    mongodb分片备份

    MongoDB 是一个高性能、开源的文档型数据库,广泛应用于各种规模的企业和项目中。在大型部署中,为了保证数据的安全性和可用性,通常会采用分片(Sharding)和复制集(Replica Set)等技术。本文将详细介绍MongoDB的...

    shell实现自动备份mongodb

    实现mongodb自定义备份,可实现自定义库、自定义集合、自定义备份周期,使用方便,脚本易维护!

    mongoDB LINUX增量备份

    - **LINUX版**:在Linux操作系统上执行的MongoDB备份操作,利用Linux的命令行工具和特性。 以上就是在Linux环境下为MongoDB执行增量备份的详细步骤,以及相关知识点的介绍。通过合理的备份策略和自动化流程,可以...

    Mongodb实现定时备份与恢复的方法教程

    本文主要介绍了关于Mongodb实现定时备份与恢复的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: MongoDB 数据备份 在 MongoDB 中我们使用 mongodump 命令来备份 MongoDB 数据 语法如下: > ...

    阿里云MongoDB备份恢复功能说明和原理介绍.pdf

    阿里云MongoDB的备份与恢复功能是一套针对MongoDB云数据库服务设计的备份机制,旨在帮助用户有效地管理和恢复数据。在讨论备份与恢复功能之前,我们先了解一下MongoDB的基本概念。 MongoDB是一种面向文档的数据库...

    django+mongodb+hui 实现的后台管理系统.zip

    django+mongodb+hui 实现的后台管理系统.zipdjango+mongodb+hui 实现的后台管理系统.zipdjango+mongodb+hui 实现的后台管理系统.zipdjango+mongodb+hui 实现的后台管理系统.zipdjango+mongodb+hui 实现的后台管理...

    基于Mysql和MongoDB的协同备份方案研究与实现.pdf

    4. 协同备份的必要性:如果两个数据库数据带有相关性,需要一起协同备份,那么备份实现就复杂了。因此,需要开发一个协同备份方案来解决这个问题。 5. 基于Mysql和MongoDB的协同备份方案:本文介绍了一种基于Mysql...

    mongodb备份数据库

    除了 mongodump 和 mongorestore,MongoDB还支持其他备份策略,如Oplog Tailoring(利用操作日志进行增量备份)和云备份服务(如MongoDB Atlas提供的自动备份)。对于生产环境,通常推荐使用更全面的备份方案,包括...

    MongoDB实现备份压缩的方法教程

    在这个例子中,`<hostname>`、`<port>`、`<username>`、`<password>` 和 `<backup_directory>` 需要替换为实际的MongoDB服务器信息和备份目标路径。 2. 备份完成后,备份文件将以`.gz`格式保存,这意味着它们已经被...

    mongodb备份

    以下是对 MongoDB 备份命令的详细解释,以及如何使用 JSON 和 CSV 格式进行数据导出和导入。 1. **MongoDB 备份命令**: MongoDB 提供了两种主要的备份方法:`mongodump` 和 ` mongorestore`。`mongodump` 用于...

    网易游戏MongoDB数据备份与恢复实践.pdf

    本文将详细介绍网易游戏MongoDB数据备份与恢复实践,涵盖了MongoDB在网易游戏端游数据中心的应用、扩展性、业务需求、priority=0资源情况等多方面的内容,并对MongoDB在网易游戏的应用进行了详细的分析和实践。...

    一个简单的MongoDB备份脚本示例,这个脚本将使用MongoDB自带的mongodump工具来备份数据库

    该脚本使用MongoDB自带的`mongodump`工具来进行数据库备份,并通过一系列命令实现了基本的备份流程管理。下面将详细解析脚本中涉及的关键知识点。 #### 二、脚本关键组成部分 ##### 1. 定义MongoDB连接参数 - **`...

    MongoDB秒级备份恢复方案.pptx

    MongoDB 秒级备份恢复方案 ...本资源总结了 MongoDB 秒级备份恢复方案的技术创新和解决方案,包括备份恢复方案的重要性、备份策略、逻辑备份 vs 物理备份、增量备份原理、问题与挑战和解决方案等内容。

    mongodb备份集的搭建

    MongoDB 是一个流行的开源...总之,MongoDB备份集的搭建是实现高可用性和数据安全的重要步骤。正确配置和管理备份集能够有效提升系统的稳定性和容灾能力。在实际操作中,务必遵循最佳实践,并进行适当的监控和维护。

    Flink CDC MongoDB Connector 的实现原理和使用实践.pdf

    MongoDB CDC Connector 实现原理和使用实践 Flink CDC MongoDB Connector 是一种实时数据同步解决方案,旨在解决 MongoDB 数据变更捕获和实时数据同步问题。本文将详细介绍 MongoDB CDC Connector 的实现原理和使用...

    MongoDB自动备份脚本

    MongoDB自动备份脚本,自动删除几天前的备份,带全部注释

Global site tag (gtag.js) - Google Analytics