文章目录
什么是副本集
MongoDB副本集(Replica Set)是一种数据冗余和故障恢复机制,它允许你维护相同数据的一个或多个副本,并提供自动故障转移和数据恢复能力。副本集是一个包含多个MongoDB实例(通常称为成员)的集合,其中一个成员被选举为主节点(Primary),其他成员作为从节点(Secondary)或仲裁节点(Arbiter)。
副本集的角色:
- 主节点(Primary):负责处理客户端的读写请求,并将数据更改写入其本地数据文件中。同时,主节点还会将这些更改记录在一个名为oplog(操作日志)的特殊日志文件中,并异步地复制给从节点。
- 从节点(Secondary):从主节点复制数据,并在本地存储一份副本。默认情况下,从节点默认不处理客户端的读请求,但你可以将其配置为可以读取,从而分散读请求并提高性能。在发生故障时,一个从节点可以被选举为主节点。
- 仲裁节点(Arbiter):只参与故障转移投票,不存储数据。它通常用于确保副本集具有奇数个成员(以实现多数投票),同时减少存储成本。
副本集的工作机制:
- 数据复制:主节点将oplog中的更改异步复制到从节点。
- 故障转移:如果主节点不可用,副本集中的其他成员将尝试选举一个新的主节点。这个过程基于心跳检测和投票机制。
- 读请求路由:客户端可以将读请求发送到主节点或从节点(如果配置为可读)。
副本集至少需要3个成员,可以配置为一主两从
如果主节点挂掉,两个从节点会重新选举,找到一个从节点,将其提升为主
在某些情况下(例如存在一个主节点和一个从节点,但由于成本有限无法再添加另一个从节点),您可以选择将一个实例配置为仲裁节点添加到副本集中。仲裁节点参与选举,但不持有数据(即不提供数据冗余):
在选举时,主节点可能降为从节点,从节点也可能提升为主节点,但仲裁节点永远只能是仲裁节点。
数据同步原理
Primary节点写入数据,Secondary通过读取Primary的oplog得到复制信息,开始复制数据并且将复制信息写入到自己的oplog。如果某个操作失败,则secondary节点停止从当前数据源复制数据。如果某个secondary节点由于某些原因挂掉了,当重新启动后,就会自动从oplog的最后一个操作开始同步,同步完成后,将信息写入自己的oplog,由于复制操作是先复制数据,复制完成后再写入oplog,有可能相同的操作会同步两份,不过MongoDB的oplog的操作是幂等的,也就是说将oplog的同一个操作执行多次,与执行一次的效果是一样的:
当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步:
- 检查自己local库的oplog.rs集合找出最近的时间戳。
- 检查Primary节点local库oplog.rs集合,找出大于此时间戳的记录。
- 将找到的记录插入到自己的oplog.rs集合中,并执行这些操作。
secondary从primary端获取日志,然后在本地完全顺序的执行oplog所记录的各种操作(oplog不记录查询操作),这个日志就是local数据库中的oplog.rs表,默认在64位机器上这个表是比较大的,占磁盘大小的5%,oplog.rs的大小可以在启动参数中设 定: --oplogSize 1000,单位是M。
注意:在副本集的环境中,要是所有的Secondary都宕机了,只剩下Primary。最后Primary会变成Secondary,不能提供服务。
oplog 讲解
部署
Docker compose 部署
创建目录,所有主机都创建
mkdir -p /docker/mongo/{data,logs}
编写 docker-compose.yml 文件,文件在 /docker/mongo 文件夹中
services:
mongo:
image: mongo:7.0
container_name: mongo
restart: always
volumes:
- /docker/mongo/data:/data/db
- /docker/mongo/logs:/var/log/mongodb
- /docker/mongo/mongodb-keyfile.key:/etc/mongodb-keyfile.key
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 123456
MONGO_INITDB_REPLICA_SET_NAME: rs0
MONGO_INITDB_DATABASE: admin
command:
- /bin/sh
- -c
- |
chmod 400 /etc/mongodb-keyfile.key
chown 999:999 /etc/mongodb-keyfile.key
mongod --replSet rs0 --bind_ip_all --auth --keyFile /etc/mongodb-keyfile.key
networks:
- mongoNet
networks:
mongoNet:
driver: bridge
在随机一台主机上生成密钥
openssl rand -base64 756 > /docker/mongo/mongodb-keyfile.key
分发给其他主机
scp /docker/mongo/mongodb-keyfile.key slave@192.168.142.156:/home/slave
scp /docker/mongo/mongodb-keyfile.key slave02@192.168.142.155:/home/slave02
scp /docker/mongo/mongodb-keyfile.key slave03@192.168.142.158:/home/slave03
在其他主机上
mv /home/<用户名>/mongodb-keyfile.key /docker/mongo
修改文件所属
chown root:root /docker/mongo/mongodb-keyfile.key
开始启动容器
docker compose up -d
当然这句话要在 /mongodb 文件夹下使用
查看集群状态
进入容器
如果 docker exec -it mongo mongosh -u root -p 123456
能直接进入,则可以免去下面创建 root 的过程
无认证登录 mongo 创建 root
docker exec -it mongo mongosh
use admin
rs.initiate()
db.createUser({user:"root",pwd:"123456",roles:[{role:"root",db:"admin"}]})
db.auth("root","123456")
添加节点
rs.add({host:"192.168.142.156:27017",priority: 2}) // 添加第一个从节点
rs.add({host:"192.168.142.155:27017",priority: 3}) // 添加第二个从节点
rs.add({host:"192.168.142.158:27017",arbiterOnly: true}) // 添加第三个从节点 [仲裁节点]
查看集群状态
rs.status()
==============================