一、高可用架构概述
1.1 为什么需要高可用
MongoDB作为NoSQL数据库的代表,广泛应用于现代互联网系统中。当数据库服务不可用时,会导致整个应用瘫痪,造成业务损失。高可用(High Availability,简称HA)架构通过冗余和故障转移机制,确保数据库服务的持续可用性,是生产环境部署的必备方案。
1.2 MongoDB高可用方案
MongoDB提供了多种高可用方案:
– 副本集(Replica Set):最基础的高可用方案,提供数据冗余和自动故障转移
– 分片集群(Sharded Cluster):支持数据分片,适合超大规模数据
– 分片+副本集组合:生产环境推荐方案,兼顾高可用和横向扩展
1.3 关键指标
| 指标 | 说明 | 目标值 |
|---|---|---|
| 可用性 | 服务可访问时间占比 | 99.95%+ |
| RPO | 恢复点目标,最大数据丢失量 | <5分钟 |
| RTO | 恢复时间目标,服务中断时长 | <30秒 |
二、Debian系统准备
2.1 环境要求
生产环境推荐配置:
– CPU:4核+
– 内存:16GB+
– 磁盘:SSD,500GB+
– 网络:千兆网络,低延迟
2.2 安装MongoDB
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装依赖
sudo apt install -y gnupg curl
# 添加MongoDB GPG密钥
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
# 添加MongoDB仓库
echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] http://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
# 安装MongoDB
sudo apt update
sudo apt install -y mongodb-org
# 启动并设置开机自启
sudo systemctl start mongod
sudo systemctl enable mongod
# 验证安装
mongosh --eval "db.adminCommand({ ping: 1 })"
2.3 配置防火墙
# 安装UFW
sudo apt install -y ufw
# 开放MongoDB端口
sudo ufw allow 27017/tcp
sudo ufw allow 27018/tcp
sudo ufw allow 27019/tcp
# 启用防火墙
sudo ufw enable
三、副本集部署
3.1 副本集原理
副本集由多个MongoDB实例组成,其中一个为主节点(Primary),其他为从节点(Secondary)。主节点处理所有写操作,从节点异步复制主节点的数据。当主节点故障时,副本集会自动选举新的主节点。
3.2 配置副本集
在所有节点上编辑MongoDB配置文件 /etc/mongod.conf:
net:
port: 27017
bindIp: 0.0.0.0
replication:
replSetName: "shard_rs"
security:
authorization: enabled
keyFile: /etc/mongo/keyfile
systemLog:
destination: file
path: /var/log/mongodb/mongod.log
logAppend: true
storage:
dbPath: /var/lib/mongodb
journal:
enabled: true
3.3 创建密钥文件
# 在主节点生成密钥
sudo openssl rand -base64 756 > /etc/mongo/keyfile
sudo chmod 400 /etc/mongo/keyfile
sudo chown mongodb:mongodb /etc/mongo/keyfile
# 将密钥复制到所有从节点
sudo scp /etc/mongo/keyfile user@secondary1:/etc/mongo/keyfile
sudo scp /etc/mongo/keyfile user@secondary2:/etc/mongo/keyfile
# 在所有从节点设置权限
sudo chmod 400 /etc/mongo/keyfile
sudo chown mongodb:mongodb /etc/mongo/keyfile
3.4 初始化副本集
连接主节点MongoDB:
mongosh --port 27017 -u admin -p --authenticationDatabase admin
执行初始化:
// 初始化副本集
rs.initiate({
_id: "shard_rs",
members: [
{ _id: 0, host: "192.168.1.101:27017", priority: 2 },
{ _id: 1, host: "192.168.1.102:27017", priority: 1 },
{ _id: 2, host: "192.168.1.103:27017", priority: 1 }
]
})
// 查看副本集状态
rs.status()
3.5 验证副本集
// 查看当前状态
rs.status()
// 查看主节点
rs.isMaster()
// 检查复制延迟
db.getMongo().getSecondaryConnection().getDB("admin").runCommand({ replSetGetStatus: 1 })
// 测试写入
db.test.insertOne({ name: "HA test", date: new Date() })
// 在从节点读取(需要配置)
db.getMongo().setReadPref('secondaryPreferred')
四、仲裁节点配置
4.1 仲裁节点作用
仲裁节点(Arbiter)不存储数据,只参与选举投票。适用于节点数为偶数时,仲裁节点可以打破平票,确保选举正常进行。
4.2 添加仲裁节点
// 添加仲裁节点
rs.addArb("192.168.1.104:27017")
// 验证配置
rs.conf()
// 查看状态
rs.status()
五、故障转移测试
5.1 模拟主节点故障
# 在主节点停止MongoDB
sudo systemctl stop mongod
5.2 观察故障转移
在从节点观察:
# 连接从节点
mongosh --port 27017 -u admin -p --authenticationDatabase admin
// 查看副本集状态
rs.status()
// 等待选举完成(约10-30秒)
// 确认新的主节点
rs.isMaster()
5.3 恢复原主节点
# 恢复原主节点
sudo systemctl start mongod
# 连接新主节点
mongosh --port 27017 -u admin -p --authenticationDatabase admin
// 触发重新选举
rs.stepDown()
六、分片集群部署
6.1 分片集群架构
分片集群由以下组件组成:
– Mongos路由节点:查询路由,不存储数据
– Config Server配置服务器:存储集群元数据
– Shard分片节点:实际存储数据
6.2 部署Config Server副本集
# 创建配置服务器数据目录
sudo mkdir -p /data/configdb
sudo chown -R mongodb:mongodb /data/configdb
# 编辑配置文件
sudo nano /etc/mongod.conf
Config Server配置:
net:
port: 27019
bindIp: 0.0.0.0
replication:
replSetName: "config_repl"
sharding:
clusterRole: configsvr
security:
authorization: enabled
keyFile: /etc/mongo/keyfile
systemLog:
destination: file
path: /var/log/mongodb/config.log
logAppend: true
初始化Config Server副本集:
mongosh --port 27019 --configsvr --replSet "config_repl"
rs.initiate({
_id: "config_repl",
configsvr: true,
members: [
{ _id: 0, host: "192.168.1.101:27019" },
{ _id: 1, host: "192.168.1.102:27019" },
{ _id: 2, host: "192.168.1.103:27019" }
]
})
6.3 部署Shard节点
Shard节点配置:
net:
port: 27018
bindIp: 0.0.0.0
replication:
replSetName: "shard1_rs"
sharding:
clusterRole: shardsvr
security:
authorization: enabled
keyFile: /etc/mongo/keyfile
systemLog:
destination: file
path: /var/log/mongodb/shard.log
logAppend: true
storage:
dbPath: /var/lib/mongodb
初始化Shard副本集:
mongosh --port 27018 --shardsvr --replSet "shard1_rs"
rs.initiate({
_id: "shard1_rs",
members: [
{ _id: 0, host: "192.168.1.104:27018", priority: 2 },
{ _id: 1, host: "192.168.1.105:27018", priority: 1 },
{ _id: 2, host: "192.168.1.106:27018", priority: 1 }
]
})
6.4 部署Mongos路由节点
# 创建Mongos配置
sudo nano /etc/mongos.conf
Mongos配置:
net:
port: 27017
bindIp: 0.0.0.0
sharding:
configDB: config_repl/192.168.1.101:27019,192.168.1.102:27019,192.168.1.103:27019
security:
authorization: enabled
keyFile: /etc/mongo/keyfile
systemLog:
destination: file
path: /var/log/mongodb/mongos.log
logAppend: true
启动Mongos:
sudo mongos -f /etc/mongos.conf
# 设置开机自启
sudo systemctl enable mongos
6.5 添加Shard到集群
# 连接Mongos
mongosh --port 27017 -u admin -p --authenticationDatabase admin
// 添加Shard
sh.addShard("shard1_rs/192.168.1.104:27018")
// 查看Shard状态
sh.status()
// 添加更多Shard
sh.addShard("shard2_rs/192.168.1.107:27018")
七、分片策略配置
7.1 分片键选择原则
分片键的选择直接影响集群性能:
– 高基数:键值唯一性要高
– 均匀分布:键值分布要均匀
– 查询友好:常用查询应包含分片键
7.2 哈希分片
适用于写入密集型场景:
// 对集合启用哈希分片
sh.shardCollection("mydb.users", { "_id": "hashed" })
// 验证分片状态
db.users.getShardDistribution()
7.3 范围分片
适用于范围查询频繁的场景:
// 对集合启用范围分片
sh.shardCollection("mydb.orders", { "created_at": 1 })
// 验证分片状态
db.orders.getShardDistribution()
7.4 复合分片键
// 使用复合键分片
sh.shardCollection("mydb.events", { "user_id": 1, "timestamp": 1 })
八、用户权限管理
8.1 创建管理员用户
// 连接MongoDB
use admin
// 创建管理员
db.createUser({
user: "siteAdmin",
pwd: "StrongPassword123!",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" }
]
})
8.2 创建应用用户
// 创建应用数据库用户
use myapp
db.createUser({
user: "appuser",
pwd: "AppUserPassword456!",
roles: [
{ role: "readWrite", db: "myapp" },
{ role: "dbAdmin", db: "myapp" }
]
})
8.3 分片集群用户权限
// 连接Mongos创建分片集群管理员
use admin
db.createUser({
user: "clusterAdmin",
pwd: "ClusterPassword789!",
roles: [
{ role: "clusterAdmin", db: "admin" },
{ role: "userAdminAnyDatabase", db: "admin" }
]
})
九、监控与维护
9.1 MongoDB监控工具
# 使用mongostat监控
mongostat -u admin -p --authenticationDatabase admin 1
# 使用mongotop监控
mongotop -u admin -p --authenticationDatabase admin 1
# 使用db.stats()查看数据库状态
db.stats()
9.2 Prometheus监控集成
安装MongoDB Exporter:
# 下载exporter
wget https://github.com/percona/mongodb_exporter/releases/download/v0.40.0/mongodb_exporter-0.40.0.linux-amd64.tar.gz
tar xzf mongodb_exporter-0.40.0.linux-amd64.tar.gz
sudo mv mongodb_exporter /usr/local/bin/
# 创建systemd服务
sudo nano /etc/systemd/system/mongodb-exporter.service
服务配置:
[Unit]
Description=MongoDB Exporter
After=network-online.target
[Service]
ExecStart=/usr/local/bin/mongodb_exporter --mongodb.uri="mongodb://admin:Password@localhost:27017/admin"
Restart=always
[Install]
WantedBy=multi-user.target
启动服务:
sudo systemctl daemon-reload
sudo systemctl start mongodb-exporter
sudo systemctl enable mongodb-exporter
9.3 备份策略
# 全量备份(副本集)
mongodump --archive=/backup/mongo_full_$(date +%Y%m%d).archive --gzip --authenticationDatabase admin -u admin -p
# 增量备份(oplog)
mongodump --archive=/backup/mongo_oplog_$(date +%Y%m%d).archive --gzip --oplog --authenticationDatabase admin -u admin -p
# 恢复
mongorestore --archive=/backup/mongo_full_20260513.archive --gzip --authenticationDatabase admin -u admin -p
十、性能优化
10.1 连接池配置
// 连接池配置
const mongoose = require('mongoose');
mongoose.connect('mongodb://appuser:Password@192.168.1.101:27017,192.168.1.102:27017,192.168.1.103:27017/myapp?replicaSet=shard_rs', {
maxPoolSize: 10,
minPoolSize: 2,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
});
10.2 索引优化
// 创建复合索引
db.users.createIndex({ "email": 1 }, { unique: true })
db.users.createIndex({ "created_at": -1, "status": 1 })
// 查看慢查询
db.getProfilingLevel()
db.setProfilingLevel(1, { slowms: 100 })
// 分析查询计划
db.users.find({ "status": "active" }).explain("executionStats")
10.3 分片均衡器
// 查看均衡器状态
sh.getBalancerState()
// 手动触发均衡
sh.moveChunk("mydb.users", { "email": "user@example.com" }, "shard2_rs")
// 设置均衡窗口
sh.setBalancerWindow(1, 6) // 凌晨1点到6点
总结
在Debian系统上部署MongoDB高可用架构需要综合考虑多个方面:
- 副本集是基础:通过副本集实现数据冗余和故障转移
- 分片集群是扩展:当数据量超过单机容量时,启用分片集群
- 安全是底线:启用认证、配置密钥文件、设置防火墙
- 监控是保障:建立完善的监控告警机制
- 备份是保险:制定并执行备份策略
通过本文介绍的方法和最佳实践,可以在Debian系统上构建一个高可用的MongoDB集群,确保数据服务的持续稳定运行。
注:本文基于MongoDB 7.0和Debian 12编写,生产环境部署前请充分测试。