基于docker-compose构建Mongodb副本集的示例详解
作者:Moment
MongoDB 副本集是一组维护相同数据集的 MongoDB 服务器。它提供了数据的高可用性和数据冗余。在一个副本集中,有一个节点被选举为 主节点(Primary)
,负责处理客户端的所有写操作。其他的 次节点(Secondary)
复制主节点的数据。
副本集的主要特点和作用包括:
高可用性:在主节点不可用时,副本集能自动选举一个新的主节点,确保服务的连续性。这对于维护业务的正常运行至关重要。
数据冗余:通过在不同服务器上复制数据,副本集提供了数据冗余,增加了数据的安全性。
故障恢复:在发生硬件故障或数据丢失时,可以从次节点恢复数据。
读写分离:虽然所有写操作都在主节点上进行,但读操作可以在次节点上进行,这样可以分散读操作带来的压力,提高读取性能。
灾难恢复:通过在物理位置不同的地方部署次节点,副本集可以提供地理冗余,从而在发生灾难时保护数据不受影响。
副本集是 MongoDB 高可用性和数据安全性策略的基础,适用于对数据安全性和服务可用性有较高要求的场景。
副本集使用场景一
假设有这样的一个场景,当多个用户或操作同时修改多条数据时,MongoDB 如何处理这些操作取决于是否使用了事务以及所使用的隔离级别。
没有使用事务
MongoDB 在没有使用事务的情况下,对于单个文档提供原子性,但不保证多个操作或多个文档更新的原子性或隔离性。这意味着如果你的第二次修改涉及到由第一次修改影响的数据,可能会遇到以下情况:
- 脏读:可能读取到其他用户正在修改但尚未完成的数据。
- 不可重复读:在同一事务内多次读取同一数据集时,可能会看到不同的数据(即,第一次读取时看到一个值,第二次读取时看到另一个值)。
- 幻读:在一次事务中,一个事务读取了几行数据,然后另一个并发事务插入了一些数据。在第一个事务再次读取时,会发现多了一些原本不存在的记录。
使用了事务
对于副本集,MongoDB 支持多文档事务。在 4.2 版本中,这个支持被扩展到了分片集群。在多文档事务中,可以包含对多个文档的多次读写操作,MongoDB 保证了以下几点:
- 原子性:事务内的所有操作要么全部成功,要么全部失败。
- 隔离性:默认情况下,MongoDB 提供了快照隔离级别,这意味着事务将看到一致的数据快照,并且在事务提交之前,其他操作无法看到事务内的更改。
如果你的第二次修改是在一个事务中,并且涉及到第一次修改的数据,MongoDB 会确保按照隔离级别处理这些更改。如果两个操作在不同的事务中,第二个事务会看到第一个事务提交的结果,前提是第一个事务已经成功提交。
虽然事务提供了更强的一致性保障,但也可能对性能有所影响。尤其是在高负载或大规模数据操作时,事务可能会导致延迟增加或资源消耗增大。
基于 docker-compose 来搭建 Mongodb 副本集
首先我们在项目的根目录下创建一个名为 docker-compose.yml 的文件,并且编写如下代码:
version: "3" services: mongodb-primary: image: mongo:latest container_name: mongodb-primary ports: - "27017:27017" environment: MONGO_INITDB_ROOT_USERNAME: moment MONGO_INITDB_ROOT_PASSWORD: moment volumes: - ./mongo-keyfile:/opt/keyfile/mongo-keyfile command: mongod --replSet rs0 --auth --keyFile /opt/keyfile/mongo-keyfile networks: - my-network mongodb-secondary: image: mongo:latest container_name: mongodb-secondary depends_on: - mongodb-primary environment: MONGO_INITDB_ROOT_USERNAME: moment MONGO_INITDB_ROOT_PASSWORD: moment volumes: - ./mongo-keyfile:/opt/keyfile/mongo-keyfile command: mongod --replSet rs0 --auth --keyFile /opt/keyfile/mongo-keyfile networks: - my-network mongodb-arbiter: image: mongo:latest container_name: mongodb-arbiter depends_on: - mongodb-primary environment: MONGO_INITDB_ROOT_USERNAME: moment MONGO_INITDB_ROOT_PASSWORD: moment volumes: - ./mongo-keyfile:/opt/keyfile/mongo-keyfile command: mongod --replSet rs0 --auth --keyFile /opt/keyfile/mongo-keyfile --oplogSize 128 networks: - my-network networks: my-network: driver: bridge
在上面的这些配置中,我们定义了三个服务:mongodb-primary、mongodb-secondary 和 mongodb-arbiter。这三个服务共同构成了一个 MongoDB 副本集。
mongodb-primary: 这是副本集的主节点。它负责处理所有的写操作,并将数据更改复制到次节点。
mongodb-secondary: 这是副本集的次节点。它从主节点复制数据,并可以在主节点不可用时被选举为新的主节点。
mongodb-arbiter: 仲裁者节点不持有数据,它的作用是在主节点故障时参与选举新的主节点。它存在是为了在有偶数个数据持有节点时提供投票机制,确保总是能够选出一个主节点。
除了这些内容之外,还有一些关键配置项:
image: 指定使用的 Docker 镜像,这里使用的是最新版的 MongoDB 官方镜像。
container_name: 为每个容器指定一个名字,如 mongodb-primary。
ports: 将容器内的 27017 端口映射到宿主机的 27017 端口上,使得可以从宿主机访问 MongoDB 服务。
environment: 设置环境变量,包括 MONGO_INITDB_ROOT_USERNAME 和 MONGO_INITDB_ROOT_PASSWORD,这些变量将被用来创建一个具有 root 权限的用户。
volumes: 将宿主机上的密钥文件 mongo-keyfile 挂载到容器内的/opt/keyfile/mongo-keyfile。这个密钥文件用于副本集成员之间的认证。
command: 容器启动时执行的命令。这里启动了 MongoDB 服务,并通过一系列参数配置了副本集、认证和密钥文件。
networks: 指定容器连接的网络。这里定义了一个名为 my-network 的自定义网络,确保容器之间能够相互通信。
depends_on: 对于次节点和仲裁者节点,这个选项指定了它们启动的依赖关系,确保它们在主节点启动后再启动。
这些配置完成之后,我们继续在 docker-compose.yml 当前文件目录下继续执行一个命令:
openssl rand -base64 756 > mongo-keyfile
在上面的这些命令中,它将生成一个 1024 位左右的 Base64 编码的随机密钥,并将其保存到名为 mongo-keyfile 的文件中。这个文件随后可以被 MongoDB 的副本集配置用作认证密钥。
keyFile 用于内部节点之间的认证。所有副本集成员使用这个共享的密钥进行相互认证,以确保只有被授权的节点可以加入副本集。
最终生成的文件内容如下图所示:
这些命令都执行完成之后,我们就可以执行 docker-compose up -d
命令来创建和启动 Mongodb 了。
当命令执行完成之后,我们可以查看 docker 容器,最终都被创建成功了
接下来我们就要执行下一个命令了,该命令的作用是启动并连接到名为 mongodb-primary 的运行中的 Docker 容器的 bash shell。一旦进入,你将能够直接在容器的命令行界面中执行命令,就像在任何标准的 Unix/Linux 命令行界面中一样:
docker exec -it mongodb-primary bash
命令执行成功之后,你会看到这样的效果:
这个时候我们需要在终端里继续执行以下命令:
mongosh "mongodb://moment:moment@localhost:27017/?authSource=admin"
这段命令的作用是启动 MongoDB Shell 并尝试使用用户名 moment 和密码 moment 在本地机器上的默认端口 27017 连接到 MongoDB 服务,并在 admin 数据库上进行认证
看到这个效果的时候说明我们的数据库已经连接成功了。
这个时候我们还差最后一步,继续在终端中输入以下命令:
rs.initiate({ _id: "rs0", members: [ { _id: 0, host: "mongodb-primary:27017" }, { _id: 1, host: "mongodb-secondary:27017" }, { _id: 2, host: "mongodb-arbiter:27017" }, ], });
该命令的作用是创建一个名为 rs0 的副本集,其中包含三个成员:一个主节点、一个次级节点和一个仲裁者节点。
当命令执行完成之后,我们在执行 rs.status() 来检查当前实例状态,如下图所示,这样的结果表示执行成功:
总结
在本篇文章中,我们学习到了如何使用 docker 来创建一个副本集,以及副本集有什么应用场景。
以上就是基于docker-compose构建Mongodb副本集的示例详解的详细内容,更多关于docker构建Mongodb副本集的资料请关注脚本之家其它相关文章!