MonoDB的复制概念与实战(详细)
一、MonoDB的复制(副本集)概念
1、复制(副本集)
- MongoDB 复制是将数据同步在多个服务器的过程。
- 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,并保证数据的安全性。
- 复制还允许您从硬件故障和服务中断中恢复数据。
2、MongoDB 复制原理
- MongoDB 之上需要两个节点。其中一个是主节点,负责处理客户端请求,其余都是从节点,负责复制主节点的数据。
- MongoDB 各个节点的常见搭配方式为:一一主一从、一主多从
- 主节点记录在其上的所有操作oplog[operation log],从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
MongoDB 复制结构图如下:
以上结构图中,客户端总主节点读取数据,在客户端写入数据到主节点是, 主节点与从节点进行数据交互保障数据的一致性。
3、MongoDB 副本集分为两种
3.1 Master-Slave 主从复制
实现数据同步只需要在某一台服务器启动时加上"-master"参数,以指明此服务器的角色是primary;另一台服务器加上"-slave"和"-source"参数,以指明此服务器的角色是slave
**注意:**MongoDB 的最新版本已不再推荐此方案。主从复制虽然可以承受一定的负载压力,但这种方式仍然是一个单点,如果主库挂了,数据写入就成了风险。
3.2 Replica Sets 复制集
Replica Sets的结构类似一个集群,完全可以把它当成一个集群,因为它确实与集群实现的作用是一样的:如果其中一个节点出现故障,其他节点马上会将业务接管过来而无须停机操作
3.3 副本集的成员
主节点
副本集的主节点是唯一一个可以接受写操作的成员。MongoDB在主节点 上应用写操作,然后将这些操作记录到主节点的oplog中。从节点成员复制这个日志然后应用到它们的数据集中。
在下图的三成员副本集中,主节点接受所有写操作。然后从节点复制oplog应用至它们的数据集中。
注意:副本集所有的成员都可以接受读操作。但是,默认情况下,应用程序会将其读操作定向至主节点,要使Secondary能支持读,需要连接到Secondary的mongod,使用rs.slaveOk() 允许从节点有查询功能,但此时他还是不支持写操作。
从节点
一个从节点维护了主节点数据集的一个副本。为了复制数据,从节点通过异步的方式将主节点oplog 应用至自己的数据集中。一个副本集可以有一个或多个从节点。
从节点可以成为主节点。如果当前主节点不可用,副本集会发起选举来选择哪个从节点成为新的主节点。
仲裁节点
在某些情况下(例如有一个主节点和一个从节点,但由于成本约束无法添加另一个从节点),你可以在副本集中添加一个仲裁节点。仲裁节点没有数据集的副本,并且不能成为主节点。然而,仲裁节点可以参与主节点选举。一个仲裁节点只有 1
票选举权。
3.4 副本集中的方法
可以通过**rs.help()**返回副本集功能的基本帮助文档
方法名 | 描述 |
---|---|
rs.status() | #返回关于副本集状态信息的文档 |
rs.initiate() | #初始化新的副本集,使用默认设置 |
rs.initiate(cfg) | #初始化新的副本集,使用指定设置 |
rs.config() | #返回副本集的配置内容 |
rs.add() | #将成员添加到副本集 |
rs.addArb() | #将仲裁节点添加到副本集 |
rs.remove() | #将成员从副本集中移除 |
rs.isMaster() | #是否是主节点 |
rs.slaveOk() | #allow queries on secondary nodes |
rs.slaveOk()
Provides a shorthand for the following operation:
db.getMongo().setSlaveOk()
This allows the current connection to allow read operations to run on secondary members. See the readPref() method for more fine-grained control over read preference in the mongo shell.
二、Replica Set 实战
Replica Set 实战 <- 这篇文章详细的阐述了如何在三台机器上搭建副本集
由于演示的方便,这里我们在一台机器上使用不同的端口来区分副本集中位于不同服务器中的节点。
配置信息 | SERVER-1 | SERVER-2 | SERVER-3 |
---|---|---|---|
数据文件存储路径 | /data/db/rs0 | /data/db/rs1 | /data/db/rs2 |
日志文件存储路径 | /data/log/rs0.log | /data/log/rs1.log | /data/log/rs2.log |
配置文件存储路径 | /data/conf/rs0.conf | /data/conf/rs1.conf | /data/conf/rs2.conf |
示例监听端口 | 40000 | 40001 | 40002 |
第一步:安装MongoDB 创建相关文件夹
我的MongoDB数据库安装在 “D:\software\mongodb” ,在该目录下(即bin的同级目录)创建data文件夹
- 在data 文件夹下创建db、log、conf文件夹,分别用于保存数据、日志、配置。
- 在db 文件夹下创建rs0、rs1、rs2 三个文件夹
- 在conf 文件夹下创建rs0.conf、rs1.conf、rs2.conf三个配置文件。
第二步:进行副本集节点的配置
主节点配置文件信息
dbpath=D:\software\mongodb\data\db\rs0 #数据输出路径
logpath=D:\software\mongodb\data\log\rs0.log #日志输出路径
logappend=true #错误日志采用追加模式
journal=true #启用日志文件
quiet=true #过滤无用的日志信息
port=40000 #默认端口号
replSet=rs #设置副本集名称
从节点配置信息
dbpath=D:\software\mongodb\data\db\rs1 #数据输出路径
logpath=D:\software\mongodb\data\log\rs1.log #日志输出路径
logappend=true #错误日志采用追加模式
journal=true #启用日志文件
quiet=true #过滤无用的日志信息
port=40001 #默认端口号
replSet=rs #设置副本集名称
仲裁节点配置信息
dbpath=D:\software\mongodb\data\db\rs2 #数据输出路径
logpath=D:\software\mongodb\data\log\rs2.log #日志输出路径
logappend=true #错误日志采用追加模式
journal=true #启用日志文件
quiet=true #过滤无用的日志信息
port=40002 #默认端口号
replSet=rs #设置副本集名称
以上三个节点的副本集名字统一为rs
第三步: 以配置文件conf启动mongod服务
mongod有几种启动方式,在这里只是用了配置文件的启动方式
打开三个cmd,输入以下命令启动mongod服务(因为我配置了环境变量,所以可以在任意路径下使用mongod命令)
//主节点以配置文件rs1.conf启动mongod服务
mongod --config D:\software\mongodb\data\conf\rs0.conf
//从节点以配置文件rs1.conf启动mongod服务
mongod --config D:\software\mongodb\data\conf\rs1.conf
//仲裁节点以配置文件rs2.conf启动mongod服务
mongod --config D:\software\mongodb\data\conf\rs2.conf
注意:启动后不要关闭命令窗口
第四步:打开mongodb客户端,设置主从节点
1、再打开一个cmd输入命令 mongo --port 40000 启动rs0客户端
2、接着输入 rs.initiate() ,初始化并使用默认设置
3、输入 rs.config() ,返回配置内容
4、输入 rs.add(“localhost:40001”),向主节点中添加从节点
出现错误:
Either all host names in a replica set configuration must be localhost references, or none must be; found 1 out of 2
//在副本集中所有的主机名要么都是localhost,要么都不是,已经发现了一个
原因:
当你在一个客户端输入rs.initiate()初始化一个副本集时,那么这个实例将添加到副本集成员中,当你输入rs.status(),查看该节点状态时,你会发现该成员name为 ”LAPTOP-N42V75IR:40000“,所以当你向添加另一个成员到副本集中,应该使用rs.add(“LAPTOP-N42V75IR:40001”)
解决:
使用rs.add(“LAPTOP-N42V75IR:40001”)进行添加
解决途径:
mongodb localhost replicasetup - Stack Overflow
5、输入 rs.addArb(“localhost:40002”),向主节点中添加仲裁节点
6、mongodb复制集创建完成,输入rs.status(),查看主节点状态
rs:PRIMARY> rs.status()
{
"set" : "rs",
"date" : ISODate("2020-11-28T15:09:54.663Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1606576194, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1606576194, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1606576194, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "LAPTOP-N42V75IR:40000",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 2265,
"optime" : {
"ts" : Timestamp(1606576194, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-11-28T15:09:54Z"),
"electionTime" : Timestamp(1606574221, 2),
"electionDate" : ISODate("2020-11-28T14:37:01Z"),
"configVersion" : 3,
"self" : true
},
{
"_id" : 1,
"name" : "LAPTOP-N42V75IR:40001",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 68,
"optime" : {
"ts" : Timestamp(1606576184, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1606576184, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-11-28T15:09:44Z"),
"optimeDurableDate" : ISODate("2020-11-28T15:09:44Z"),
"lastHeartbeat" : ISODate("2020-11-28T15:09:54.032Z"),
"lastHeartbeatRecv" : ISODate("2020-11-28T15:09:54.038Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "LAPTOP-N42V75IR:40000",
"configVersion" : 3
},
{
"_id" : 2,
"name" : "LAPTOP-N42V75IR:40002",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 12,
"lastHeartbeat" : ISODate("2020-11-28T15:09:54.035Z"),
"lastHeartbeatRecv" : ISODate("2020-11-28T15:09:54.118Z"),
"pingMs" : NumberLong(0),
"configVersion" : 3
}
],
"ok" : 1
}
验证
验证:主节点负责数据的读写,从节点只负责读。仲裁节点不负责数据的存储。
方法:向主节点插入一个集合,观察从节点和仲裁节点是否存在刚才向主节点插入的集合
操作:
use test
db.createCollection("testCollection")
打开图形化工具,连接各个端口实例,这时候观察主节点(40000)和从节点(40001)都会增加一个新的数据库test和新的集合testCollection,而仲裁节点则没有。
验证成功!
参考
上一篇: 数据中间件 MyCAT 源码析 — SQL ON MonoDB
下一篇: B-Tree、B+Tree