MongoDB生产环境踩坑记录

MongoDB生产环境踩坑记录

去年在生产环境折腾MongoDB,踩了不少坑,这里记录下关键问题。

安装与初始配置

CentOS 7安装

yum安装比手动下载省心,版本管理也方便。

创建仓库文件

1
vim /etc/yum.repos.d/mongodb-org-4.2.repo

配置文件内容如下:

1
2
3
4
5
6
[mongodb-org-4.2]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.2/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc
1
yum install -y mongodb-org

装完之后有这几个组件:

  • mongod:数据库进程
  • mongo:命令行客户端
  • mongos:分片路由

数据目录配置

默认在 /var/lib/mongo,生产环境最好单独挂个数据盘:

1
2
mkdir -p /data/mongodb
chown -R mongod:mongod /data/mongodb

配置文件

生产环境的配置建议:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log

storage:
dbPath: /data/mongodb
journal:
enabled: true
wiredTiger:
engineConfig:
cacheSizeGB: 4 # 根据内存调整

processManagement:
fork: true
pidFilePath: /var/run/mongodb/mongod.pid

net:
port: 27017
bindIp: 127.0.0.1,10.0.0.1 # 记得加内网IP

security:
authorization: enabled

关键配置说明:

配置项 说明 建议值
cacheSizeGB WiredTiger缓存 内存的50%
bindIp 绑定IP 包含内网IP
authorization 认证 生产必须开

用户权限管理

生产环境第一步就是创建管理员账户。

创建root用户

1
2
3
4
5
6
7
8
9
10
11
12
mongo

use admin

db.createUser({
user: "root",
pwd: "YourStrongPassword123",
roles: [
{role: "root", db: "admin"},
{role: "userAdminAnyDatabase", db: "admin"}
]
})

角色权限说明

角色 权限 场景
root 超级用户 系统管理员
dbAdmin 数据库管理 维护
readWrite 读写 应用连接
read 只读 数据分析
clusterAdmin 集群管理 分片集群

修改密码

1
2
3
4
5
6
7
8
9
10
mongo -u root -p YourStrongPassword123 localhost:27017/admin

use admin
db.updateUser('root', {
pwd: 'NewStrongPassword456',
roles: [
{role: 'root', db: 'admin'},
{role: 'userAdminAnyDatabase', db: 'admin'}
]
})

防火墙配置

记得给MongoDB配置白名单:

1
2
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="27017" accept'
firewall-cmd --reload

数据备份与恢复

mongodumpmongorestore 是标配工具。

数据库导出

1
2
3
4
5
6
7
8
9
# 导出单个数据库
mongodump -d dr -o /data/backup/db/dr/

# 远程备份(带认证)
mongodump --host dds-xxx.mongodb.rds.aliyuncs.com:1111 \
--username root \
--password xxxxxx \
--authenticationDatabase admin \
-d dr -o /data/backup/db/dr/

数据库导入

1
2
3
4
5
6
7
8
9
10
# 恢复数据到本地
mongorestore -d dr --dir /data/backup/db/dr/dr/

# 恢复到云端
mongorestore --host dds-xxxx.mongodb.rds.aliyuncs.com:1111,\
dds-xxxx.mongodb.rds.aliyuncs.com:1111 \
--username root \
--password xxxxx \
--authenticationDatabase admin \
-d dr --dir /data/backup/db/dr/dr/

自动备份脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
YMDAY=$(date +%Y-%m-%d-%H-%M-%S)
BACKUP_DIR="/data/db/dumps/mongodb"
DB_NAME="production_db"

mongodump --host xxxxx \
--username backup_user \
--password backup_pass \
--authenticationDatabase admin \
-d $DB_NAME \
-o $BACKUP_DIR/${DB_NAME}_${YMDAY}/

# 保留7天
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} \;

加到crontab:

1
0 2 * * * /bin/bash /data/scripts/backup_mongodb.sh >> /var/log/mongodb_backup.log 2>&1

远程连接

阿里云MongoDB连接

1
2
3
4
5
mongo admin --username root \
--host dds-xxx.mongodb.rds.aliyuncs.com:1111,\
dds-xxx.mongodb.rds.aliyuncs.com:1111 \
--port 1111 \
--password xxxx

Node.js连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const mongoose = require('mongoose');

const mongoConfig = {
uri: 'mongodb://root:xxx@dds-xxx.mongodb.rds.aliyuncs.com:1111,' +
'dds-xxx.mongodb.rds.aliyuncs.com:1111/dancingRoad' +
'?replicaSet=mgset-xxx&authSource=admin',
options: {
db: { safe: true },
useNewUrlParser: true,
useUnifiedTopology: true
}
};

mongoose.connect(mongoConfig.uri, mongoConfig.options)
.then(() => console.log('MongoDB连接成功'))
.catch(err => console.error('MongoDB连接失败:', err));

Windows远程访问配置

开发环境配置:

  1. 打开网络配置,选择”专用网络”
  2. 修改配置 C:\Program Files\MongoDB\Server\4.2\bin\mongod.cfg
1
2
net:
bindIp: 0.0.0.0
  1. 重启服务

性能优化

内存配置

WiredTiger缓存默认公式:

1
缓存大小 = MAX((总内存 × 50% - 1GB), 256MB)

生产环境建议显式配置:

1
2
3
4
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 4 # 根据实际内存调整

内存配置参考:

服务器内存 cacheSizeGB 说明
8GB 3GB 保留系统内存
16GB 7GB 中等规模
32GB 15GB 大数据集
64GB+ 28GB 考虑分片

数据库操作优化

批量更新:

1
2
3
4
5
6
7
8
9
10
11
db.users.find({"status": "pending"}).forEach(
function(item) {
db.users.update(
{"_id": item._id},
{"$set": {
"updatedAt": new Date(),
"status": "processed"
}}
);
}
);

删除字段:

1
2
3
4
5
db.collection.update(
{},
{$unset: {"deprecatedField": ""}},
{multi: true}
);

索引优化

1
2
3
4
5
6
7
8
// 复合索引
db.orders.createIndex({"userId": 1, "createTime": -1});

// 唯一索引
db.users.createIndex({"email": 1}, {unique: true});

// 查看执行计划
db.orders.find({"userId": "u12345"}).explain("executionStats");

日志分析

1
2
3
4
5
6
7
8
9
# 查看进程
ps -ef | grep mongo

# 查看日志路径
cat /usr/local/mongodb/mongodb.conf | grep logpath

# 搜索特定操作
cat /var/log/mongodb/mongod.log | grep dropDatabase
cat /var/log/mongodb/mongod.log | grep "slow query"

高可用架构

副本集

1
2
replication:
replSetName: rs0

优点:

  • 数据冗余,自动故障转移
  • 读操作可分担到Secondary
  • 支持滚动升级

分片集群

组件 功能
mongos 查询路由,负载均衡
config server 存储元数据
shard 数据分片存储

故障排查

常见问题

连接认证失败

1
MongoNetworkError: connection refused

解决:

  1. 检查 bindIp 配置是否包含客户端IP
  2. 确认防火墙已放行
  3. 验证用户名密码

内存使用过高

1
2
db.serverStatus().mem
db.serverStatus().connections

监控指标

指标 告警阈值 说明
连接数 > 80% 连接池耗尽
内存使用率 > 90% 可能OOM
慢查询比例 > 5% 需优化索引
复制延迟 > 10s 主从同步延迟

小结

这篇文章记录了我在MongoDB生产环境部署中遇到的问题和解决方案。主要是配置优化、权限管理、备份策略和性能调优几个方面。希望对你有帮助。


有问题欢迎交流。