基于docker-compose构建Mongodb副本集

MongoDB 副本集是一组维护相同数据集的 MongoDB 服务器。它提供了数据的高可用性和数据冗余。在一个副本集中,有一个节点被选举为 主节点(Primary),负责处理客户端的所有写操作。其他的 次节点(Secondary) 复制主节点的数据。

副本集的主要特点和作用包括:

  1. 高可用性:在主节点不可用时,副本集能自动选举一个新的主节点,确保服务的连续性。这对于维护业务的正常运行至关重要。

  2. 数据冗余:通过在不同服务器上复制数据,副本集提供了数据冗余,增加了数据的安全性。

  3. 故障恢复:在发生硬件故障或数据丢失时,可以从次节点恢复数据。

  4. 读写分离:虽然所有写操作都在主节点上进行,但读操作可以在次节点上进行,这样可以分散读操作带来的压力,提高读取性能。

  5. 灾难恢复:通过在物理位置不同的地方部署次节点,副本集可以提供地理冗余,从而在发生灾难时保护数据不受影响。

副本集是 MongoDB 高可用性和数据安全性策略的基础,适用于对数据安全性和服务可用性有较高要求的场景。

副本集使用场景一

假设有这样的一个场景,当多个用户或操作同时修改多条数据时,MongoDB 如何处理这些操作取决于是否使用了事务以及所使用的隔离级别。

没有使用事务

MongoDB 在没有使用事务的情况下,对于单个文档提供原子性,但不保证多个操作或多个文档更新的原子性或隔离性。这意味着如果你的第二次修改涉及到由第一次修改影响的数据,可能会遇到以下情况:

  • 脏读:可能读取到其他用户正在修改但尚未完成的数据。
  • 不可重复读:在同一事务内多次读取同一数据集时,可能会看到不同的数据(即,第一次读取时看到一个值,第二次读取时看到另一个值)。
  • 幻读:在一次事务中,一个事务读取了几行数据,然后另一个并发事务插入了一些数据。在第一个事务再次读取时,会发现多了一些原本不存在的记录。

使用了事务

对于副本集,MongoDB 支持多文档事务。在 4.2 版本中,这个支持被扩展到了分片集群。在多文档事务中,可以包含对多个文档的多次读写操作,MongoDB 保证了以下几点:

  • 原子性:事务内的所有操作要么全部成功,要么全部失败。
  • 隔离性:默认情况下,MongoDB 提供了快照隔离级别,这意味着事务将看到一致的数据快照,并且在事务提交之前,其他操作无法看到事务内的更改。

如果你的第二次修改是在一个事务中,并且涉及到第一次修改的数据,MongoDB 会确保按照隔离级别处理这些更改。如果两个操作在不同的事务中,第二个事务会看到第一个事务提交的结果,前提是第一个事务已经成功提交。

虽然事务提供了更强的一致性保障,但也可能对性能有所影响。尤其是在高负载或大规模数据操作时,事务可能会导致延迟增加或资源消耗增大。

基于 docker-compose 来搭建 Mongodb 副本集

首先我们在项目的根目录下创建一个名为 docker-compose.yml 的文件,并且编写如下代码:

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 副本集。

  1. mongodb-primary: 这是副本集的主节点。它负责处理所有的写操作,并将数据更改复制到次节点。

  2. mongodb-secondary: 这是副本集的次节点。它从主节点复制数据,并可以在主节点不可用时被选举为新的主节点。

  3. mongodb-arbiter: 仲裁者节点不持有数据,它的作用是在主节点故障时参与选举新的主节点。它存在是为了在有偶数个数据持有节点时提供投票机制,确保总是能够选出一个主节点。

除了这些内容之外,还有一些关键配置项:

  1. image: 指定使用的 Docker 镜像,这里使用的是最新版的 MongoDB 官方镜像。

  2. container_name: 为每个容器指定一个名字,如 mongodb-primary。

  3. ports: 将容器内的 27017 端口映射到宿主机的 27017 端口上,使得可以从宿主机访问 MongoDB 服务。

  4. environment: 设置环境变量,包括 MONGO_INITDB_ROOT_USERNAME 和 MONGO_INITDB_ROOT_PASSWORD,这些变量将被用来创建一个具有 root 权限的用户。

  5. volumes: 将宿主机上的密钥文件 mongo-keyfile 挂载到容器内的/opt/keyfile/mongo-keyfile。这个密钥文件用于副本集成员之间的认证。

  6. command: 容器启动时执行的命令。这里启动了 MongoDB 服务,并通过一系列参数配置了副本集、认证和密钥文件。

  7. networks: 指定容器连接的网络。这里定义了一个名为 my-network 的自定义网络,确保容器之间能够相互通信。

  8. depends_on: 对于次节点和仲裁者节点,这个选项指定了它们启动的依赖关系,确保它们在主节点启动后再启动。

这些配置完成之后,我们继续在 docker-compose.yml 当前文件目录下继续执行一个命令:

bash 复制代码
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 命令行界面中一样:

bash 复制代码
docker exec -it mongodb-primary bash

命令执行成功之后,你会看到这样的效果:

这个时候我们需要在终端里继续执行以下命令:

bash 复制代码
mongosh "mongodb://moment:moment@localhost:27017/?authSource=admin"

这段命令的作用是启动 MongoDB Shell 并尝试使用用户名 moment 和密码 moment 在本地机器上的默认端口 27017 连接到 MongoDB 服务,并在 admin 数据库上进行认证

看到这个效果的时候说明我们的数据库已经连接成功了。

这个时候我们还差最后一步,继续在终端中输入以下命令:

js 复制代码
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 来创建一个副本集,以及副本集有什么应用场景。

相关推荐
天上掉下来个程小白6 分钟前
案例-14.文件上传-简介
数据库·spring boot·后端·mybatis·状态模式
Asthenia04121 小时前
基于Jackson注解的JSON工具封装与Redis集成实战
后端
编程星空1 小时前
css主题色修改后会多出一个css吗?css怎么定义变量?
开发语言·后端·rust
林的快手1 小时前
CSS列表属性
前端·javascript·css·ajax·firefox·html5·safari
sszdzq2 小时前
Docker
运维·docker·容器
程序员侠客行2 小时前
Spring事务原理 二
java·后端·spring
匹马夕阳2 小时前
ECharts极简入门
前端·信息可视化·echarts
dmy2 小时前
docker 快速构建开发环境
后端·docker·容器
API_technology2 小时前
电商API安全防护:JWT令牌与XSS防御实战
前端·安全·xss
sjsjsbbsbsn2 小时前
Spring Boot定时任务原理
java·spring boot·后端