搞了老长时间,MongoDB真的我哭死🥹

前言

想着MongoDB不是支持事务了嘛,我就想在服务里面加上MongoDB的事务功能,然后百度到使用MongoDB事务,必须要开启副本集才行,然后顺藤摸瓜,就跑去弄了三个副本集,以下主要是配置副本集的踩坑日志

踩坑一:副本集鉴权

MongoDB如果配置用户名密码鉴权,就必须要在各个服务之间加上公用的keyfile

自己生成一个随机的keyfile

1
2
openssl rand -base64 756 > <path-to-keyfile>
chmod 400 <path-to-keyfile>

在conf中加入如下配置

1
2
3
security:
authorization: enabled # 启用身份验证
keyFile: <path-to-keyfile>

踩坑二:不能获取密钥文件

报错如下:

1
{"error":"Location5579201: Unable to acquire security key[s]"}

这是因为你的文件权限太低或者太高了(MongoDB会检查文件权限)

MongoDB官方要求keyfile的权限为400,并且mongodb为所有者

在Docker挂载卷设置这个权限还不行,要在Docker容器内部设置

所以在容器启动MongoDB服务之前,你必须要设置好容器内的keyfile文件权限

在你的启动文件前加上如下代码

1
2
chown mongodb:mongodb <path-to-keyfile>
chmod 400 <path-to-keyfile>

这样就不会报错了

踩坑三:环境变量配置鉴权不生效

使用环境变量初始化用户名和密码

1
2
3
environment:
MONGO_INITDB_ROOT_USERNAME: <username>
MONGO_INITDB_ROOT_PASSWORD: <password>

罪魁祸首如下:

1
command: ["/bin/bash", "/entrypoint.sh"]

使用command命令之后,Docker不会执行MongoDB官网提供的docker-entrypoint.sh脚本,而从环境变量初始化用户名和密码就是通过官方提供的启动脚本进行的,所以指定command之后,环境变量不会生效

采取措施:在自己的sh脚本下使用官方的sh脚本启动MongoDB

1
2
3
MONGO_CONFIG="/etc/mongo/mongod.conf"
# 启动官方脚本(附带自定义配置)
/usr/local/bin/docker-entrypoint.sh --config $MONGO_CONFIG

踩坑四:使用容器名初始化副本集

错误示例如下:

1
2
3
4
5
6
7
8
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongo1:27017" },
{ _id: 1, host: "mongo2:27018" },
{ _id: 2, host: "mongo3:27019" }
]
});

这样会导致连接不上MongoDB副本集,因为MongoDB真的会直接返回容器名,不会返回真实域名或者IP

(另外,MongoDB提倡使用固定域名初始化副本集,防止IP地址变更造成的麻烦)

官方正确示例如下,直接指定域名或者IP:

1
2
3
4
5
6
7
8
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "mongodb0.example.net:27017" },
{ _id: 1, host: "mongodb1.example.net:27017" },
{ _id: 2, host: "mongodb2.example.net:27017" }
]
})

撒花完结

踩完以上坑后,就可以美美使用MongoDB副本集事务啦🌸🌸🌸

另外,附上我的Docker Compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mongo1:
image: mongo:latest
container_name: mongo1
hostname: mongo1
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: <username>
MONGO_INITDB_ROOT_PASSWORD: <password>
volumes:
- ./cumt-forum/mongo/data/mongo1:/data/db
- ./cumt-forum/mongo/mongo-keyfile:/data/mongo-keyfile
- ./cumt-forum/mongo/conf/mongod.conf:/etc/mongo/mongod.conf
- ./cumt-forum/mongo/conf/entrypoint.sh:/entrypoint.sh
command: ["/bin/bash", "/entrypoint.sh"]
depends_on:
- mongo2
- mongo3
restart: always
networks:
- cumt-forum

还有启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

# 设置密钥文件的权限
echo "Setting permissions for keyfile..."
chown mongodb:mongodb /data/mongo-keyfile
chmod 400 /data/mongo-keyfile

# 设置 MongoDB 配置文件
MONGO_CONFIG="/etc/mongo/mongod.conf"

# 启动 MongoDB 服务
echo "Starting MongoDB with config file: $MONGO_CONFIG"
/usr/local/bin/docker-entrypoint.sh --config $MONGO_CONFIG

如果解决了你的问题、或者还有其他问题,欢迎在评论区留言