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
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
|
数据备份与恢复
mongodump 和 mongorestore 是标配工具。
数据库导出
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}/
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远程访问配置
开发环境配置:
- 打开网络配置,选择”专用网络”
- 修改配置
C:\Program Files\MongoDB\Server\4.2\bin\mongod.cfg:
- 重启服务
性能优化
内存配置
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
|
解决:
- 检查
bindIp 配置是否包含客户端IP
- 确认防火墙已放行
- 验证用户名密码
内存使用过高
1 2
| db.serverStatus().mem db.serverStatus().connections
|
监控指标
| 指标 |
告警阈值 |
说明 |
| 连接数 |
> 80% |
连接池耗尽 |
| 内存使用率 |
> 90% |
可能OOM |
| 慢查询比例 |
> 5% |
需优化索引 |
| 复制延迟 |
> 10s |
主从同步延迟 |
小结
这篇文章记录了我在MongoDB生产环境部署中遇到的问题和解决方案。主要是配置优化、权限管理、备份策略和性能调优几个方面。希望对你有帮助。
有问题欢迎交流。