有一个使用 mongodb 做数据库的项目要上生产了,所以在生产环境规划了两台机器用于搭建数据库主从,但是调研搭建的过程中发现主从模式还是有些缺陷,mongodb 提供了另一种复制模式替代主从模式。
mongodb 总共有四种部署模式:
1.单机模式;
2.主从模式;主节点挂了,需要手动把从节点切换成主节点继续提供服务。
3.复制模式;主节点挂了,复制节点会自动选举新的主节点。
4.集群模式;磁盘瓶颈,单节点能力瓶颈推荐使用集群模式进行能力扩展。

复制集通过 replSetInitiate 命令(或mongoshell的rs.initiate())进行初始化,初始化后各个成员间开始发送心跳消息,并发起 Primary 选举操作,获得大多数成员投票支持的节点,会成为 Primary,其余节点成为 Secondary。
假设复制集内投票成员数量为N(Primary+Secondary),则大多数为 N/2 + 1,当复制集内存活成员数量不足大多数时,整个复制集将无法选举出Primary,复制集将无法提供写服务,处于只读状态。
| 投票成员数 | 大多数 | 容忍失效数 |
|---|---|---|
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 3 | 2 |
| 6 | 4 | 2 |
| 7 | 4 | 3 |
根据上表,N 最少也需要3个。
每个复制节点都有优先级,选举时一般会先选优先级最大的。另外还有两类特殊 Secondary 节点,一类是优先级为0的(从Primary复制数据,不会被选为Primary),另一类是Arbiter(不复制数据,只有选举功能,可参与投票,本身不会被选为Primary)。
因为之前是计划主从模式部署,只申请了两台机器,后面调研发现复制模式比较好,所以计划是 Primary + Secondary + Arbiter 部署,Primary 使用一台服务器,Secondary + Arbiter 使用另一台服务器。
搭建之前先找一台机器模拟搭建下,相关版本信息如下:
机器配置和mongodb版本:
- 服务器:Alibaba Cloud Linux release 3 (Soaring Falcon)【对标的reahat8】
- mongodb版本:5.0.5
规划启动三个 mongodb 进程,分别占用27017(Primary )、27018(Secondary )、27019(Arbiter )端口;每个部署相对独立,部署可参考linux 单机部署 mongodb。
目录规划:
- # 端口27017的mongodb目录
- /apps/program/mongodb-0
-
- # 端口27018的mongodb目录
- /apps/program/mongodb-1
-
- # 端口27019的mongodb目录
- /apps/program/mongodb-2
-
-
- 每个目录下另创建目录
- data 存放数据
- logs 存放日志
- etc 存放配置文件
Primary 配置文件如下,另外两个配置文件相应修改目录和端口即可。
- systemLog:
- # 日志输出目的地,可以指定为“ file”或者“syslog”
- destination: file
- # 日志存储路径
- path: /apps/program/mongodb-0/logs/mongodb.log
- logAppend: true
- storage:
- # 是否开启journal日志持久存储
- journal:
- enabled: true
- dbPath: /apps/program/mongodb-0/data
- # 是否将不同DB的数据存储在不同的目录中
- directoryPerDB: true
- engine: wiredTiger
- wiredTiger:
- engineConfig:
- # 数据占用内存的大小
- cacheSizeGB: 0.5
- processManagement:
- # 是否后台启动
- fork: true
- # 进程文件
- pidFilePath: /apps/program/mongodb-0/mongod.pid
- net:
- # 可访问的地址
- bindIp: 0.0.0.0
- # 进程端口
- port: 27017
- security:
- # 是否开启用户访问控制
- authorization: enabled
- # 集群之间的认证模式
- clusterAuthMode: keyFile
- # 当认证模式为keyFile时,该文件的路径
- keyFile: /apps/program/mongodb-0/keyFile
- replication:
- # oplog的大小,类似mysql的binlog
- oplogSizeMB: 512
- # 复制集的名称
- replSetName: fuzhiji
keyFile 的内容其实没有太多约束,例如可以使用 openssl 随机生成100字符的base64编码:
openssl rand -base64 100 > ./keyFile
keyFile 权限是 400,复制集的每个keyFile要完全一致。
切换到mongodb的bin目录下,分别使用对应的配置文件启动三个进程:
./mongod -f /apps/program/mongodb-*/etc/mongodb.conf
登录任意一个可用mongodb数据库:
- # 登入任意一台数据库
- ./mongo --host localhost --port 27017
-
- # 声明复制集的配置
- config={_id:'fuzhiji',
- members:[
- {_id: 0, host: 'localhost:27017',priority:2},
- {_id: 1, host: 'localhost:27018',priority:1},
- {_id: 2, host: 'localhost:27019',arbiterOnly:true}
- ]
- }
-
- #复制集配置生效
- rs.initiate(config)
命令执行后,该连接命令窗口就会出现该连接的节点属性:

- # 查看当前复制集集群中成员的配置
- rs.config()
-
- # 查看主节点
- db.isMaster()
-
- # 查看复制集集群成员状态
- rs.status()
-
- # 新增节点到复制集
- rs.add('ip:port')
-
- # 从复制集删除节点
- rs.remove('ip:port')
-
- # 新增仲裁节点
- rs.addArb('ip:port')
-
- # 允许在Secondary节点可以进行查询,需要在副本节点上操作
- rs.secondaryOk()
-
- # 查看当前连接
- db.getMongo()
-
- # 修改节点优先级,需要在Primary节点操作,操作前需要切到 admin 进行认证
- config=rs.config()
- config.members[1].priority=5
- rs.reconfig(config)
1.官方配置文件说明:5.0版本配置文件配置项