docker · 2024-04-30 0

docker-compose 搭建 mongodb 副本集

一、搭建

主从复制和副本集区别:

主从集群和副本集最大的区别就是副本集没有固定的主节点;整个集群会选出一个主节点,当其挂掉后,又在剩下的从节点中选中其他节点为主节点,副本集总有一个主节点和一个或多个备份节点。

docker-compose 配置复制集只要注意几点:

  1. command 执行命令时需要指定 --keyFile 和 --replSet 两个属性。keyFile 是为了添加复制集时的验证处理,拥有同样的 keyFile 文件的节点才可以被添加到复制集中。
  2. docker-compose 配置复制集需要指定 –replSet 属性值,否则直接配置直接失败。

副本集的集合名 replSetName 必须是相同的

1.拉取镜像

docker pull mongo:5.0.6

2.使用 openssl 生成 keyFile 文件

生成 keyFile 文件:

openssl rand -base64 756 > key.file

修改 keyFile 文件权限:

chmod 400 key.file
chown 999 key.file

若不修改 keyFile 文件权限,会出现 permissions on /etc/key.file are too open,这是因为 mongo key 文件权限过大造成的。

3.docker compose 启动容器

docker-compose.yml 文件:

version: '3'
services:
  mongo_1:
    image: mongo:5.0.6
    container_name: mongo_1
    restart: always
    ports:
      - 27017:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456
    volumes:
      - ./replica_set_1/data/db:/data/db
      - ./key.file:/etc/key.file
    command: --keyFile /etc/key.file --replSet rs0
    networks:
      mongo:
        ipv4_address: 172.18.1.11

  mongo_2:
    image: mongo:5.0.6
    container_name: mongo_2
    restart: always
    ports:
      - 27027:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456
    volumes:
      - ./replica_set_2/data/db:/data/db
      - ./key.file:/etc/key.file
    command: --keyFile /etc/key.file --replSet rs0
    networks:
      mongo:
        ipv4_address: 172.18.1.12

  mongo_3:
    image: mongo:5.0.6
    container_name: mongo_3
    restart: always
    ports:
      - 27037:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456
    volumes:
      - ./replica_set_3/data/db:/data/db
      - ./key.file:/etc/key.file
    command: --keyFile /etc/key.file --replSet rs0
    networks:
      mongo:
        ipv4_address: 172.18.1.13

networks:
    mongo:
        driver: bridge
        ipam:
            config:
                - subnet: 172.18.1.0/24

使用 docker compose 启动容器

docker compose -f docker-compose.yml up -d

进入容器,可以看到实际启动命令,如下:

root@3b9e1efd4bab:/# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
mongodb        1       0  1 16:20 ?        00:00:11 mongod --keyFile /etc/key.file --replSet rs0 --auth --bind_ip_all

注意,此时副本集还没有初始化,还不能使用 mongodb

4. 副本集初始化

使用 rs.initiate,进行初始化副本集

rs.initiate({
    "_id" : "rs0",
    "members" : [
        {
            "_id" : 0,
            "host" : "mongo_1:27017"
        },
        {
            "_id" : 1,
            "host" : "mongo_2:27017"
        },
        {
            "_id" : 2,
            "host" : "mongo_3:27017"
        }
    ]
}
)

rs.initiate({
    "_id" : "rs0",
    "members" : [
        {
            "_id" : 0,
            "host" : "172.18.1.11:27017"
        },
        {
            "_id" : 1,
            "host" : "172.18.1.12:27017"
        },
        {
            "_id" : 2,
            "host" : "172.18.1.13:27017"
        }
    ]
}
)

示例:

root@3b9e1efd4bab:/# mongo
> use admin
> db.auth("root","123456")
> rs.initiate({
... "_id" : "rs0",
... "members" : [
... {
... "_id" : 0,
... "host" : "mongo_1:27017"
... },
... {
... "_id" : 1,
... "host" : "mongo_2:27017"
... },
... {
... "_id" : 2,
... "host" : "mongo_3:27017"
... }
... ]
... }
... )
{ "ok" : 1 }
rs0:SECONDARY>

5.测试

找到主节点,进入 mongodb:

root@3b9e1efd4bab:/# mongo
rs0:PRIMARY> use admin
switched to db admin
rs0:PRIMARY> db.auth("root","123456")
1
rs0:PRIMARY> show databases
admin   0.000GB
config  0.000GB
local   0.000GB
rs0:PRIMARY> db.person.insert({'name': 'zhang1', 'age': '21'})
WriteResult({ "nInserted" : 1 })
rs0:PRIMARY> db.person.find()
{ "_id" : ObjectId("664e1d6f569f986f9ce44428"), "name" : "zhang1", "age" : "21" }

副本集管理命令:

命令 解释
rs.initiate() 使用默认配置初始化副本集
rs.initiate(cfg) 使用配置文件cfg初始化副本集
rs.reconfig(cfg) 修改副本集配置信息
rs.status() 查看副本集状态
rs.conf() 查看副本集配置
rs.add(hostportstr) 或 rs.add(membercfgobj) 添加新的节点
rs.addArb(hostportstr) 添加投票节点
rs.remove(hostportstr) 删除节点
rs.slaveOk() 允许从库只读,默认从库不允许读写
rs.isMaster() 查看哪个节点为主节点
rs.stepDown([stepdownSecs, catchUpSecs]) 手动主从切换

二、jdcb 操作

pom 依赖:

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.12.10</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

测试连接:

@Test
public void testConnectionWithRep() {
    // 方式一,验证连接
    String database = "admin";
    String user = "root";
    char[] password = "123456".toCharArray();

    MongoCredential credential = MongoCredential.createCredential(user, database, password);
    MongoClientOptions options = MongoClientOptions.builder().sslEnabled(false).build();
    MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("127.0.0.1", 27017),
            new ServerAddress("127.0.0.1", 27027), new ServerAddress("127.0.0.1", 27037)),
            credential, options);

    // 方式二,使用 url,验证连接
    // MongoClient mongoClient = new MongoClient(
    //         new MongoClientURI( "mongodb://root:123456@127.0.0.1:27017,127.0.0.1:27027,127.0.0.1:27037/?authSource=admin&ssl=false&replicaSet=rs0"));

    MongoCursor<String> cursor = mongoClient.listDatabaseNames().cursor();

    while (cursor.hasNext()) {
        String next = cursor.next();
        System.out.println(next);
    }
}