搭建MongoDB副本集

devtools/2024/11/14 2:06:50/

文章目录

    • 一、什么是MongoDB的副本集
    • 二、副本集的架构
    • 三、副本集的成员
    • 四、部署副本集
      • 1、节点划分
      • 2、安装MongoDB
        • 2.1、下载解压安装包
      • 3、创建主节点
        • 3.1、创建存储数据和日志的目录
        • 3.2、新建配置文件
        • 3.3、启动节点服务
      • 4、创建副本节点
        • 4.1、创建存储数据和日志的目录
        • 4.2、新建配置文件
        • 4.3、启动节点服务
      • 5、创建仲裁节点
        • 5.1、创建存储数据和日志的目录
        • 5.2、创建配置文件
        • 5.3、启动节点服务
      • 6、添加环境变量
      • 7、初始化副本集
        • 7.1、客户端连接主节点
        • 7.2、初始化副本集
      • 8、查看副本集配置信息
      • 9、添加副本节点和仲裁节点
      • 10、再次查看副本集配置信息
      • 11、设置副本节点可读
    • 五、测试副本集的数据读写操作
      • 1、主节点测试
      • 2、副本节点测试
        • 2.1、设置副本节点只能作为备份不能读取
      • 3、仲裁节点不存放任何数据
    • 六、主节点的选举原则
      • 1、主节点选举触发条件
      • 2、选举规则
    • 七、集群故障分析
      • 1、主节点故障
      • 2、副本节点故障
      • 3、仲裁节点故障
      • 4、主节点和仲裁节点故障
      • 5、从节点和仲裁节点故障
      • 6、主节点和从节点故障
      • 7、所有节点故障

一、什么是MongoDB的副本集

MongoDB的副本集(Replica Set)是一种提供数据冗余和高可用性的架构。它是由多个维护相同数据集的mongod进程(即数据库实例)组成的一个集合,这些实例分布在不同的服务器上。

副本集的设计目标是为了确保在单个服务器发生故障时,数据库服务依然可以继续运作,从而提高了系统的可靠性和容错能力。

二、副本集的架构

  • 一个副本集最多有50个节点。一个副本集最多有7个投票节点,其余节点必须是没有投票权的节点。

  • 副本集的最小推荐配置是三个节点:

    • 一个主节点和两个从节点。
    • 一个主节点、一个从节点和仲裁节点。

2270526-20220923193134773-2055031891

2270526-20220923185546781-845092680

三、副本集的成员

副本集有两种类型三种角色

  • 两种类型

    • 主节点(Primary)类型:数据操作的主要连接点,可读写

    • 次要(辅助、从)节点(Secondaries)类型:数据冗余备份节点,可以读或选举

  • 三种角色

    • 主要成员(Primary):主要接收所有写操作。就是主节点。

    • 副本成员(Replicate):从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操作,但可以读操作(但需要配置)。是默认的一种从节点类型

    • 仲裁者(Arbiter):不保留任何数据的副本,只具有投票选举作用,当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。

  • 建议

    • 如果你的副本+主节点的个数是偶数,建议加一个仲裁者,形成奇数,容易满足大多数的投票。

    • 如果你的副本+主节点的个数是奇数,可以不加仲裁者。

四、部署副本集

u=3763007939,3474838561&fm=253&fmt=auto&app=138&f=PNG

1、节点划分

一台机器上部署三个mongodb节点

端口角色
27017主节点
27018副本节点
27019仲裁节点

2、安装MongoDB

2.1、下载解压安装包
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.6.tgz
tar xzvf mongodb-linux-x86_64-rhel70-4.4.6.tgz -C /usr/local
cd /usr/local/
ln -s /usr/local/mongodb-linux-x86_64-rhel70-4.4.6 /usr/local/mongodb

3、创建主节点

3.1、创建存储数据和日志的目录
mkdir -p /usr/local/mongodb/replica_sets/myrs_27017/log
mkdir -p /usr/local/mongodb/replica_sets/myrs_27017/data/db
3.2、新建配置文件
vim /usr/local/mongodb/replica_sets/myrs_27017/mongod.confsystemLog:destination: filepath: "/usr/local/mongodb/replica_sets/myrs_27017/log/mongod.log"logAppend: true
storage:dbPath: "/usr/local/mongodb/replica_sets/myrs_27017/data/db"journal:# 启用持久性日志enabled: true
processManagement:fork: truepidFilePath: "/usr/local/mongodb/replica_sets/myrs_27017/log/mongod.pid"
net:bindIp: localhost,192.168.112.40port: 27017
replication:replSetName: myrs
3.3、启动节点服务
[root@localhost local]# /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27017/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 8177
child process started successfully, parent exiting

4、创建副本节点

4.1、创建存储数据和日志的目录
mkdir -p /usr/local/mongodb/replica_sets/myrs_27018/log
mkdir -p /usr/local/mongodb/replica_sets/myrs_27018/data/db
4.2、新建配置文件
vim /usr/local/mongodb/replica_sets/myrs_27018/mongod.confsystemLog:destination: filepath: "/usr/local/mongodb/replica_sets/myrs_27018/log/mongod.log"logAppend: true
storage:dbPath: "/usr/local/mongodb/replica_sets/myrs_27018/data/db"journal:enabled: true
processManagement:fork: truepidFilePath: "/usr/local/mongodb/replica_sets/myrs_27018/log/mongod.pid"
net:bindIp:  localhost,192.168.112.40port: 27018
replication:replSetName: myrs
4.3、启动节点服务
[root@localhost ~]# /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27018/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 18263
child process started successfully, parent exiting

5、创建仲裁节点

5.1、创建存储数据和日志的目录
mkdir -p /usr/local/mongodb/replica_sets/myrs_27019/log
mkdir -p /usr/local/mongodb/replica_sets/myrs_27019/data/db
5.2、创建配置文件
vim /usr/local/mongodb/replica_sets/myrs_27019/mongod.confsystemLog:destination: filepath: "/usr/local/mongodb/replica_sets/myrs_27019/log/mongod.log"logAppend: true
storage:dbPath: "/usr/local/mongodb/replica_sets/myrs_27019/data/db"journal:# 启用持久性日志enabled: true
processManagement:fork: truepidFilePath: "/usr/local/mongodb/replica_sets/myrs_27019/log/mongod.pid"
net:bindIp:  localhost,192.168.112.40port: 27019
replication:replSetName: myrs
5.3、启动节点服务
[root@localhost ~]# /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27019/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 18314
child process started successfully, parent exiting

6、添加环境变量

vim /etc/profileexport PATH=/usr/local/mongodb/bin/:$PATHsource /etc/profile
[root@localhost ~]# which mongo
/usr/local/mongodb/bin/mongo

7、初始化副本集

7.1、客户端连接主节点
mongo --host 192.168.112.40 --port=27017
7.2、初始化副本集

当前并未选举主节点(primary),并且操作没有设置为允许从辅助节点(secondary)上读取。

所以很多命令无法使用,必须初始化副本集

> show dbs
uncaught exception: Error: listDatabases failed:{"topologyVersion" : {"processId" : ObjectId("662f9e53d74e84faba8865bc"),"counter" : NumberLong(0)},"ok" : 0,"errmsg" : "not master and slaveOk=false","code" : 13435,"codeName" : "NotPrimaryNoSecondaryOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1

初始化副本集

> rs.initiate()
{"info2" : "no configuration specified. Using a default configuration for the set","me" : "192.168.112.40:27017","ok" : 1
}
myrs:SECONDARY>

image-20240429215626296

  • "ok"的值为1,说明创建成功。

  • 命令行提示符发生变化,变成了一个从节点角色,此时默认不能读写。

  • 稍等片刻,发现副本集只有自己一个,变成主节点。

8、查看副本集配置信息

myrs:PRIMARY> rs.conf()
{"_id" : "myrs","version" : 1,"term" : 1,"protocolVersion" : NumberLong(1),"writeConcernMajorityJournalDefault" : true,"members" : [{"_id" : 0,"host" : "192.168.112.40:27017","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1}],"settings" : {"chainingAllowed" : true,"heartbeatIntervalMillis" : 2000,"heartbeatTimeoutSecs" : 10,"electionTimeoutMillis" : 10000,"catchUpTimeoutMillis" : -1,"catchUpTakeoverDelayMillis" : 30000,"getLastErrorModes" : {},"getLastErrorDefaults" : {"w" : 1,"wtimeout" : 0},"replicaSetId" : ObjectId("662fa69cd74e84faba8865e0")}
}
  • “_id” : “myrs” :副本集的配置数据存储的主键值,默认就是副本集的名字

  • “members” :副本集成员数组,此时只有一个:“host” : “192.168.112.40:27017”

  • 该成员不是仲裁节点: “arbiterOnly” : false

  • 优先级(权重值): “priority” : 1

  • “settings” :副本集的参数配置。

9、添加副本节点和仲裁节点

添加副本节点

myrs:PRIMARY> rs.add("192.168.112.40:27018")
{"ok" : 1,"$clusterTime" : {"clusterTime" : Timestamp(1714399646, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}},"operationTime" : Timestamp(1714399646, 1)
}

添加仲裁节点

myrs:PRIMARY> rs.addArb("192.168.112.40:27019")
{"ok" : 1,"$clusterTime" : {"clusterTime" : Timestamp(1714399738, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}},"operationTime" : Timestamp(1714399738, 1)
}

10、再次查看副本集配置信息

myrs:PRIMARY> rs.conf()
{"_id" : "myrs","version" : 3,"term" : 1,"protocolVersion" : NumberLong(1),"writeConcernMajorityJournalDefault" : true,"members" : [{"_id" : 0,"host" : "192.168.112.40:27017","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 1,"host" : "192.168.112.40:27018","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 2,"host" : "192.168.112.40:27019","arbiterOnly" : true,"buildIndexes" : true,"hidden" : false,"priority" : 0,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1}],"settings" : {"chainingAllowed" : true,"heartbeatIntervalMillis" : 2000,"heartbeatTimeoutSecs" : 10,"electionTimeoutMillis" : 10000,"catchUpTimeoutMillis" : -1,"catchUpTakeoverDelayMillis" : 30000,"getLastErrorModes" : {},"getLastErrorDefaults" : {"w" : 1,"wtimeout" : 0},"replicaSetId" : ObjectId("662fa69cd74e84faba8865e0")}
}
  • 成员信息:
    • 成员1(_id: 0)和成员2(_id: 1)都是数据承载节点,它们位于同一台机器的不同端口(27017 和 27018)。两者都有相同的优先级(“priority” : 1),意味着它们都可以成为主节点。它们都没有延迟复制(“slaveDelay” : NumberLong(0)),并且都参与选举投票(“votes” : 1)。
    • 成员3(_id: 2)是一个仲裁者(arbiterOnly: true),位于端口27019。仲裁者的角色是在选举新主节点时起到决定性的一票作用,但它不存储实际数据,也没有优先级,不参与数据复制。

11、设置副本节点可读

rs.slaveOk()

五、测试副本集的数据读写操作

1、主节点测试

[root@localhost ~]# mongo --port 27017myrs:PRIMARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
myrs:PRIMARY> use test1
switched to db test1
myrs:PRIMARY> db.q1.insert({"id":"1000","content":"学习部署副本集","userid":"001","name":"zhangsan","createdatatime":new Date(),"state":null})
WriteResult({ "nInserted" : 1 })
myrs:PRIMARY> db.q1.find().pretty()
{"_id" : ObjectId("662fb0d727a6cea3c847b26e"),"id" : "1000","content" : "学习部署副本集","userid" : "001","name" : "zhangsan","createdatatime" : ISODate("2024-04-29T14:38:15.243Z"),"state" : null
}

2、副本节点测试

[root@localhost ~]# mongo --port 27018myrs:SECONDARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
test1   0.000GB
myrs:SECONDARY> use test1
switched to db test1
myrs:SECONDARY> show tables;
q1
myrs:SECONDARY> db.q1.find().pretty()
{"_id" : ObjectId("662fb0d727a6cea3c847b26e"),"id" : "1000","content" : "学习部署副本集","userid" : "001","name" : "zhangsan","createdatatime" : ISODate("2024-04-29T14:38:15.243Z"),"state" : null
}
myrs:SECONDARY> db.q1.insert({"id":"1001","content":"学习部署副本集","userid":"002","name":"lisi","createdatatime":new Date(),"state":null})
WriteCommandError({"topologyVersion" : {"processId" : ObjectId("662fa148dfb1efa1f75795c3"),"counter" : NumberLong(4)},"operationTime" : Timestamp(1714402027, 1),"ok" : 0,"errmsg" : "not master","code" : 10107,"codeName" : "NotWritablePrimary","$clusterTime" : {"clusterTime" : Timestamp(1714402027, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)}}
})
  • 无法写入数据

    • “errmsg” : “not master”

    • “codeName” : “NotWritablePrimary”

2.1、设置副本节点只能作为备份不能读取
#设置从节点有读取权限
rs.slaveOk()
# 取消从节点的数据读取权限
rs.slaveOk(false)

3、仲裁节点不存放任何数据

[root@localhost ~]# mongo --port 27019myrs:ARBITER> show dbs
uncaught exception: Error: listDatabases failed:{"topologyVersion" : {"processId" : ObjectId("662fa25360629ad0a0f05cc1"),"counter" : NumberLong(1)},"ok" : 0,"errmsg" : "not master and slaveOk=false","code" : 13435,"codeName" : "NotPrimaryNoSecondaryOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1
myrs:ARBITER> rs.slaveOk()
WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead.
myrs:ARBITER> show dbs
uncaught exception: Error: listDatabases failed:{"topologyVersion" : {"processId" : ObjectId("662fa25360629ad0a0f05cc1"),"counter" : NumberLong(1)},"ok" : 0,"errmsg" : "node is not in primary or recovering state","code" : 13436,"codeName" : "NotPrimaryOrSecondary"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1

“errmsg” : “node is not in primary or recovering state”

仲裁节点(Arbiter)在MongoDB副本集中仅用于选举过程中的投票,并不存储数据

六、主节点的选举原则

1、主节点选举触发条件

  • MongoDB在副本集中,会自动进行主节点的选举,主节点选举的触发条件

    • 主节点故障

    • 主节点网络不可达(默认心跳信息为10秒)

    • 人工干预(rs.stepDown(600))primary直接降级在600s内不会把自己选为primary

  • 一旦触发选举,就要根据一定规则来选择主节点。

2、选举规则

  • 选举规则是根据票数来决定谁获胜

    • 票数最高,且获得了“大多数”成员的投票支持的节点获胜。

    • "大多数"的定义为:假设复制集内投票成员时N,则大多数为N/2+1。例如:3个投票成员,则大多数的值是2。当复制集内存活成员数量不足大多数时,整个复制集将无法选举primary,复制集将无法提供写服务,处于只读状态。

    • 若票数相同,且都获得了“大多数”成员的投票支持的,数据新的节点获胜。

    • 数据的新旧是通过操作日志oplog来对比的。

  • 在获得票数的时候,优先级(priority)参数影响重大。

  • 可以通过设置优先级(priority)来设置额外票数。优先级即权重,取值为0-1000,相当于增加0-1000的票数,优先级的值越大,就越可能获得多数成员的投票(votes)数。指定较高的值可使成员更有资格成员主要成员,更低的值可使成员更不符合条件。

  • 默认情况下,优先级的值是1

七、集群故障分析

1、主节点故障

  • 从节点和仲裁节点对主节点的心跳失败,当失败超过10秒,此时因为没有主节点了,会自动发起投票。
    • 而副本节点只有一台,因此,候选人只有一个就是副本节点,开始投票。
    • 仲裁节点向副本节点投了一票,副本节点本身自带一票,因此共两票,超过了"大多数"。
    • 27019是仲裁节点,没有选举权,27018不向其投票,其票数是0。
    • 最终结果,27018成为主节点。具备读写功能。
  • 再启动 27017主节点,发现27017变成了从节点,27018仍保持主节点。
  • 登录27017节点,发现是从节点了,数据自动从27018同步。
  • 此时:不影响正常使用

2、副本节点故障

  • 主节点和仲裁节点对副本节点的心跳失败。因为主节点还在,因此,没有触发投票选举。
    如果此时,在主节点写入数据。再启动从节点,会发现,主节点写入的数据,会自动同步给从节点。
  • 此时:不影响正常使用

3、仲裁节点故障

  • 主节点和副本节点对仲裁节点的心跳失败。因为主节点还在,因此,没有触发投票选举。
  • 此时:不影响正常使用

4、主节点和仲裁节点故障

副本集中没有主节点了,导致此时,副本集是只读状态,无法写入。

因为27017的票数,没有获得大多数,即没有大于等于2,它只有默认的一票(优先级是1)
如果要触发选举,随便加入一个成员即可。

  • 如果只加入 27019仲裁节点成员,则主节点一定是27017,因为没得选了,仲裁节点不参与选举,但参与投票。
  • 如果只加入 27018节点,会发起选举。因为27017和27018都是两票,则按照谁数据新,谁当主节点。

此时:影响正常使用,需要处理

5、从节点和仲裁节点故障

10秒后,27017主节点自动降级为副本节点。(服务降级)
副本集不可写数据了,已经故障了。

此时:影响正常使用,需要处理

6、主节点和从节点故障

集群将处于不完全状态,无法执行写操作,因为剩余的副本节点不足以立即选出新的主节点(假设只剩一个副本节点和仲裁节点)。直到至少有一个额外的副本节点在线并同步,以便选举出新的主节点

此时:影响正常使用,需要处理

7、所有节点故障

  • 整个集群不可用,既不能执行读也不能执行写操作。

  • 这种情况需要手动干预,逐一排查并恢复各个节点,确保至少一个主节点和多数节点(包括仲裁节点)在线,以恢复集群服务。

  • 此时:影响正常使用,需要处理


http://www.ppmy.cn/devtools/31585.html

相关文章

架构设计 | 分布式与集群有什么区别

作为一名从业多年的程序员&#xff0c;对于分布式和集群这两种架构有着深入的了解。简单来说&#xff0c;分布式是将一个任务分拆到多个节点共同完成&#xff0c;而集群则是多个节点执行相同的任务。具体来说&#xff0c;分布式和集群的区别体现在以下几个方面&#xff1a; 一…

基于Springboot的家具网站

基于SpringbootVue的家具网站设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 商家 家具信息 家居资讯 后台管理 后台首页 用户管理 商家管理 家具类型管理 家具…

文件API及其操作

这里介绍两类文件操作、三个文件类。包括文件系统操作&#xff08;File类&#xff09;、文件内容操作&#xff08;操作字节流、操作字符流&#xff09; 1.文件类File 1.1.认识File类 &#xff08;1&#xff09;什么是File类呢&#xff1f;其实就是可以操作文件的一个类。通过…

Baidu Comate:“AI +”让软件研发更高效更安全

4月27日&#xff0c;百度副总裁陈洋出席由全国工商联主办的第64届德胜门大讲堂&#xff0c;并发表了《深化大模型技术创新与应用落地&#xff0c;护航大模型产业平稳健康发展》主题演讲。陈洋表示&#xff0c;“人工智能”成为催生新质生产力的重要引擎&#xff0c;对于企业而言…

Redis高并发可用-主从复制,集群

Redis高并发可用 1 复制 默认情况下&#xff0c;Redis都是主节点。每个从节点只能有一个主节点&#xff0c;而主节点可以同时具有多个从节点。复制的数据流是单向的&#xff0c;只能由主节点复制到从节点。 1.1 复制的拓扑结构 一主一从&#xff1a; 主一从结构是最简单的…

vite+vue3配置less

在Vite项目中配置LESS&#xff0c;你需要安装相关的插件&#xff0c;并在Vite配置文件中进行配置。以下是步骤和示例代码&#xff1a; 安装LESS和LESS插件&#xff1a; npm install less --save-dev npm install less-loader --save-dev 在Vite配置文件中&#xff08;通常是v…

音视频入门基础:像素格式专题(1)——RGB简介

一、像素格式简介 像素格式&#xff08;pixel format&#xff09;指像素色彩按分量的大小和排列。这种格式以每个像素所使用的总位数以及用于存储像素色彩的红、绿、蓝和 alpha 分量的位数指定。在音视频领域&#xff0c;常用的像素格式包括RGB格式和YUV格式&#xff0c;本文…

docker学习笔记4:CentOS7安装docker

文章目录 一、安装docker二、配置阿里云加速三、测试镜像安装本篇博客介绍如何在centos7里安装docker,关于CentOS7的安装可以查看本专栏的这篇博客: VmWare CentOS7安装与静态ip配置 centos7里安装docker步骤如下: 一、安装docker 先在终端输入su进入root用户,输入如下命…