第138集MongoDB集群架构运维实战
|字数总计:5.6k|阅读时长:24分钟|阅读量:
1. MongoDB集群架构概述
MongoDB集群架构是构建高可用、高性能、可扩展数据库系统的核心技术。通过合理的集群架构设计,可以实现数据的高可用性、负载均衡、水平扩展等功能。本文将详细介绍MongoDB集群架构的各种类型、部署方法、运维管理技巧以及在企业级应用中的最佳实践。
1.1 集群架构的核心价值
- 高可用性: 通过副本集实现数据冗余和故障转移
- 水平扩展: 通过分片集群实现数据的水平扩展
- 负载均衡: 通过分片实现读写负载的分散
- 数据安全: 通过多副本保证数据的安全性
- 性能优化: 通过集群架构提升整体性能
1.2 集群架构类型
- 副本集(Replica Set): 数据冗余和故障转移
- 分片集群(Sharded Cluster): 水平扩展和负载均衡
- 混合架构: 副本集 + 分片集群的组合
- 多数据中心: 跨数据中心的集群部署
2. MongoDB副本集架构
2.1 副本集基础配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
| #!/bin/bash
REPLICA_SET_NAME="rs0" MONGO_PORT=27017 DATA_DIR="/data/mongodb" LOG_DIR="/var/log/mongodb" CONFIG_DIR="/etc/mongodb"
create_directories() { echo "创建MongoDB目录结构..." mkdir -p $DATA_DIR/{primary,secondary1,secondary2} chown -R mongodb:mongodb $DATA_DIR mkdir -p $LOG_DIR chown -R mongodb:mongodb $LOG_DIR mkdir -p $CONFIG_DIR chown -R mongodb:mongodb $CONFIG_DIR echo "目录创建完成" }
generate_config() { echo "生成MongoDB配置文件..." cat > $CONFIG_DIR/mongod-primary.conf << EOF # MongoDB主节点配置文件 # @author 运维实战
# 基本配置 storage: dbPath: $DATA_DIR/primary journal: enabled: true commitIntervalMs: 100
# 网络配置 net: port: $MONGO_PORT bindIp: 0.0.0.0 maxIncomingConnections: 1000
# 日志配置 systemLog: destination: file path: $LOG_DIR/mongod-primary.log logAppend: true logRotate: reopen
# 进程管理 processManagement: fork: true pidFilePath: $DATA_DIR/primary/mongod.pid
# 副本集配置 replication: replSetName: $REPLICA_SET_NAME
# 安全配置 security: authorization: enabled keyFile: $CONFIG_DIR/keyfile
# 性能优化 operationProfiling: slowOpThresholdMs: 100 mode: slowOp
# 内存配置 storage: wiredTiger: engineConfig: cacheSizeGB: 2 journalCompressor: snappy directoryForIndexes: true collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true EOF
cat > $CONFIG_DIR/mongod-secondary1.conf << EOF # MongoDB从节点1配置文件 # @author 运维实战
# 基本配置 storage: dbPath: $DATA_DIR/secondary1 journal: enabled: true commitIntervalMs: 100
# 网络配置 net: port: $((MONGO_PORT + 1)) bindIp: 0.0.0.0 maxIncomingConnections: 1000
# 日志配置 systemLog: destination: file path: $LOG_DIR/mongod-secondary1.log logAppend: true logRotate: reopen
# 进程管理 processManagement: fork: true pidFilePath: $DATA_DIR/secondary1/mongod.pid
# 副本集配置 replication: replSetName: $REPLICA_SET_NAME
# 安全配置 security: authorization: enabled keyFile: $CONFIG_DIR/keyfile
# 性能优化 operationProfiling: slowOpThresholdMs: 100 mode: slowOp
# 内存配置 storage: wiredTiger: engineConfig: cacheSizeGB: 2 journalCompressor: snappy directoryForIndexes: true collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true EOF
cat > $CONFIG_DIR/mongod-secondary2.conf << EOF # MongoDB从节点2配置文件 # @author 运维实战
# 基本配置 storage: dbPath: $DATA_DIR/secondary2 journal: enabled: true commitIntervalMs: 100
# 网络配置 net: port: $((MONGO_PORT + 2)) bindIp: 0.0.0.0 maxIncomingConnections: 1000
# 日志配置 systemLog: destination: file path: $LOG_DIR/mongod-secondary2.log logAppend: true logRotate: reopen
# 进程管理 processManagement: fork: true pidFilePath: $DATA_DIR/secondary2/mongod.pid
# 副本集配置 replication: replSetName: $REPLICA_SET_NAME
# 安全配置 security: authorization: enabled keyFile: $CONFIG_DIR/keyfile
# 性能优化 operationProfiling: slowOpThresholdMs: 100 mode: slowOp
# 内存配置 storage: wiredTiger: engineConfig: cacheSizeGB: 2 journalCompressor: snappy directoryForIndexes: true collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true EOF
echo "配置文件生成完成" }
generate_keyfile() { echo "生成MongoDB密钥文件..." openssl rand -base64 756 > $CONFIG_DIR/keyfile chmod 600 $CONFIG_DIR/keyfile chown mongodb:mongodb $CONFIG_DIR/keyfile echo "密钥文件生成完成" }
start_mongodb() { echo "启动MongoDB服务..." mongod --config $CONFIG_DIR/mongod-primary.conf sleep 5 mongod --config $CONFIG_DIR/mongod-secondary1.conf sleep 5 mongod --config $CONFIG_DIR/mongod-secondary2.conf sleep 5 echo "MongoDB服务启动完成" }
init_replica_set() { echo "初始化MongoDB副本集..." mongo --port $MONGO_PORT << EOF // 初始化副本集配置 // @author 运维实战
rs.initiate({ _id: "$REPLICA_SET_NAME", members: [ { _id: 0, host: "localhost:$MONGO_PORT", priority: 2 }, { _id: 1, host: "localhost:$((MONGO_PORT + 1))", priority: 1 }, { _id: 2, host: "localhost:$((MONGO_PORT + 2))", priority: 1 } ] });
// 等待副本集初始化完成 while (rs.status().ok !== 1) { print("等待副本集初始化..."); sleep(1000); }
// 创建管理员用户 use admin; db.createUser({ user: "admin", pwd: "admin123", roles: [ { role: "root", db: "admin" }, { role: "clusterAdmin", db: "admin" } ] });
// 创建应用用户 use appdb; db.createUser({ user: "appuser", pwd: "app123", roles: [ { role: "readWrite", db: "appdb" } ] });
print("副本集初始化完成"); EOF
echo "副本集初始化完成" }
main() { echo "开始部署MongoDB副本集..." create_directories generate_config generate_keyfile start_mongodb init_replica_set echo "MongoDB副本集部署完成!" echo "主节点: localhost:$MONGO_PORT" echo "从节点1: localhost:$((MONGO_PORT + 1))" echo "从节点2: localhost:$((MONGO_PORT + 2))" }
main "$@"
|
2.2 副本集管理脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
| #!/bin/bash
REPLICA_SET_NAME="rs0" MONGO_PORT=27017 ADMIN_USER="admin" ADMIN_PASS="admin123"
check_replica_set_status() { echo "检查副本集状态..." mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 检查副本集状态 // @author 运维实战
use admin;
// 显示副本集状态 print("=== 副本集状态 ==="); rs.status();
// 显示副本集配置 print("\n=== 副本集配置 ==="); rs.conf();
// 显示副本集健康状态 print("\n=== 副本集健康状态 ==="); rs.printSlaveReplicationInfo();
// 显示副本集统计信息 print("\n=== 副本集统计信息 ==="); rs.printReplicationInfo(); EOF
echo "副本集状态检查完成" }
add_replica_set_member() { local host=$1 local port=$2 local priority=${3:-1} echo "添加副本集成员: $host:$port (优先级: $priority)..." mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 添加副本集成员 // @author 运维实战
use admin;
// 添加新成员 rs.add({ host: "$host:$port", priority: $priority });
// 等待成员同步 while (rs.status().members.length < 4) { print("等待新成员加入..."); sleep(1000); }
print("新成员添加完成"); EOF
echo "副本集成员添加完成" }
remove_replica_set_member() { local host=$1 local port=$2 echo "移除副本集成员: $host:$port..." mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 移除副本集成员 // @author 运维实战
use admin;
// 移除成员 rs.remove("$host:$port");
print("成员移除完成"); EOF
echo "副本集成员移除完成" }
reconfigure_replica_set() { echo "重新配置副本集..." mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 重新配置副本集 // @author 运维实战
use admin;
// 获取当前配置 var config = rs.conf();
// 修改配置 config.members[0].priority = 2; config.members[1].priority = 1; config.members[2].priority = 1;
// 应用新配置 rs.reconfig(config);
print("副本集重新配置完成"); EOF
echo "副本集重新配置完成" }
force_election() { echo "强制重新选举主节点..." mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 强制重新选举主节点 // @author 运维实战
use admin;
// 强制重新选举 rs.stepDown();
print("主节点重新选举完成"); EOF
echo "主节点重新选举完成" }
backup_replica_set() { local backup_dir=$1 local backup_name=$(date +%Y%m%d_%H%M%S) echo "备份副本集到: $backup_dir/$backup_name..." mkdir -p $backup_dir/$backup_name mongodump --host localhost:$MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin --out $backup_dir/$backup_name echo "副本集备份完成" }
restore_replica_set() { local backup_dir=$1 local backup_name=$2 echo "从备份恢复副本集: $backup_dir/$backup_name..." mongorestore --host localhost:$MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin $backup_dir/$backup_name echo "副本集恢复完成" }
main() { case $1 in "status") check_replica_set_status ;; "add") add_replica_set_member $2 $3 $4 ;; "remove") remove_replica_set_member $2 $3 ;; "reconfig") reconfigure_replica_set ;; "election") force_election ;; "backup") backup_replica_set $2 ;; "restore") restore_replica_set $2 $3 ;; *) echo "用法: $0 {status|add|remove|reconfig|election|backup|restore}" echo " status - 检查副本集状态" echo " add <host> <port> [priority] - 添加副本集成员" echo " remove <host> <port> - 移除副本集成员" echo " reconfig - 重新配置副本集" echo " election - 强制重新选举主节点" echo " backup <backup_dir> - 备份副本集" echo " restore <backup_dir> <backup_name> - 恢复副本集" ;; esac }
main "$@"
|
3. MongoDB分片集群架构
3.1 分片集群部署脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
| #!/bin/bash
SHARD_NAME="shard0" CONFIG_SERVER_NAME="configReplSet" MONGO_PORT=27017 CONFIG_PORT=27018 MONGOS_PORT=27019 DATA_DIR="/data/mongodb" LOG_DIR="/var/log/mongodb" CONFIG_DIR="/etc/mongodb"
create_shard_directories() { echo "创建分片集群目录结构..." mkdir -p $DATA_DIR/{shard0-primary,shard0-secondary1,shard0-secondary2} mkdir -p $DATA_DIR/{shard1-primary,shard1-secondary1,shard1-secondary2} mkdir -p $DATA_DIR/{config-primary,config-secondary1,config-secondary2} mkdir -p $LOG_DIR mkdir -p $CONFIG_DIR chown -R mongodb:mongodb $DATA_DIR chown -R mongodb:mongodb $LOG_DIR chown -R mongodb:mongodb $CONFIG_DIR echo "分片集群目录创建完成" }
generate_shard_config() { echo "生成分片集群配置文件..." cat > $CONFIG_DIR/mongod-shard0-primary.conf << EOF # MongoDB分片0主节点配置文件 # @author 运维实战
# 基本配置 storage: dbPath: $DATA_DIR/shard0-primary journal: enabled: true commitIntervalMs: 100
# 网络配置 net: port: $MONGO_PORT bindIp: 0.0.0.0 maxIncomingConnections: 1000
# 日志配置 systemLog: destination: file path: $LOG_DIR/mongod-shard0-primary.log logAppend: true logRotate: reopen
# 进程管理 processManagement: fork: true pidFilePath: $DATA_DIR/shard0-primary/mongod.pid
# 副本集配置 replication: replSetName: $SHARD_NAME
# 分片配置 sharding: clusterRole: shardsvr
# 安全配置 security: authorization: enabled keyFile: $CONFIG_DIR/keyfile
# 性能优化 operationProfiling: slowOpThresholdMs: 100 mode: slowOp
# 内存配置 storage: wiredTiger: engineConfig: cacheSizeGB: 2 journalCompressor: snappy directoryForIndexes: true collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true EOF
cat > $CONFIG_DIR/mongod-config-primary.conf << EOF # MongoDB配置服务器主节点配置文件 # @author 运维实战
# 基本配置 storage: dbPath: $DATA_DIR/config-primary journal: enabled: true commitIntervalMs: 100
# 网络配置 net: port: $CONFIG_PORT bindIp: 0.0.0.0 maxIncomingConnections: 1000
# 日志配置 systemLog: destination: file path: $LOG_DIR/mongod-config-primary.log logAppend: true logRotate: reopen
# 进程管理 processManagement: fork: true pidFilePath: $DATA_DIR/config-primary/mongod.pid
# 副本集配置 replication: replSetName: $CONFIG_SERVER_NAME
# 分片配置 sharding: clusterRole: configsvr
# 安全配置 security: authorization: enabled keyFile: $CONFIG_DIR/keyfile
# 性能优化 operationProfiling: slowOpThresholdMs: 100 mode: slowOp
# 内存配置 storage: wiredTiger: engineConfig: cacheSizeGB: 1 journalCompressor: snappy directoryForIndexes: true collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true EOF
cat > $CONFIG_DIR/mongos.conf << EOF # MongoDB Mongos配置文件 # @author 运维实战
# 网络配置 net: port: $MONGOS_PORT bindIp: 0.0.0.0 maxIncomingConnections: 1000
# 日志配置 systemLog: destination: file path: $LOG_DIR/mongos.log logAppend: true logRotate: reopen
# 进程管理 processManagement: fork: true pidFilePath: $DATA_DIR/mongos.pid
# 分片配置 sharding: configDB: $CONFIG_SERVER_NAME/localhost:$CONFIG_PORT,localhost:$((CONFIG_PORT + 1)),localhost:$((CONFIG_PORT + 2))
# 安全配置 security: keyFile: $CONFIG_DIR/keyfile
# 性能优化 operationProfiling: slowOpThresholdMs: 100 mode: slowOp EOF
echo "分片集群配置文件生成完成" }
start_shard_cluster() { echo "启动分片集群..." mongod --config $CONFIG_DIR/mongod-config-primary.conf mongod --config $CONFIG_DIR/mongod-config-secondary1.conf mongod --config $CONFIG_DIR/mongod-config-secondary2.conf sleep 10 mongod --config $CONFIG_DIR/mongod-shard0-primary.conf mongod --config $CONFIG_DIR/mongod-shard0-secondary1.conf mongod --config $CONFIG_DIR/mongod-shard0-secondary2.conf sleep 10 mongos --config $CONFIG_DIR/mongos.conf sleep 5 echo "分片集群启动完成" }
init_shard_cluster() { echo "初始化分片集群..." mongo --port $CONFIG_PORT << EOF // 初始化配置服务器副本集 // @author 运维实战
rs.initiate({ _id: "$CONFIG_SERVER_NAME", members: [ { _id: 0, host: "localhost:$CONFIG_PORT" }, { _id: 1, host: "localhost:$((CONFIG_PORT + 1))" }, { _id: 2, host: "localhost:$((CONFIG_PORT + 2))" } ] });
print("配置服务器副本集初始化完成"); EOF
mongo --port $MONGO_PORT << EOF // 初始化分片副本集 // @author 运维实战
rs.initiate({ _id: "$SHARD_NAME", members: [ { _id: 0, host: "localhost:$MONGO_PORT" }, { _id: 1, host: "localhost:$((MONGO_PORT + 1))" }, { _id: 2, host: "localhost:$((MONGO_PORT + 2))" } ] });
print("分片副本集初始化完成"); EOF
mongo --port $MONGOS_PORT << EOF // 添加分片到集群 // @author 运维实战
use admin;
// 添加分片 sh.addShard("$SHARD_NAME/localhost:$MONGO_PORT,localhost:$((MONGO_PORT + 1)),localhost:$((MONGO_PORT + 2))");
// 启用分片 sh.enableSharding("testdb");
// 设置分片键 sh.shardCollection("testdb.users", { "userId": 1 });
print("分片集群初始化完成"); EOF
echo "分片集群初始化完成" }
main() { echo "开始部署MongoDB分片集群..." create_shard_directories generate_shard_config generate_keyfile start_shard_cluster init_shard_cluster echo "MongoDB分片集群部署完成!" echo "Mongos: localhost:$MONGOS_PORT" echo "配置服务器: localhost:$CONFIG_PORT" echo "分片服务器: localhost:$MONGO_PORT" }
main "$@"
|
3.2 分片集群管理脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
| #!/bin/bash
MONGOS_PORT=27019 ADMIN_USER="admin" ADMIN_PASS="admin123"
check_shard_cluster_status() { echo "检查分片集群状态..." mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 检查分片集群状态 // @author 运维实战
use admin;
// 显示分片状态 print("=== 分片状态 ==="); sh.status();
// 显示分片统计信息 print("\n=== 分片统计信息 ==="); sh.getBalancerState();
// 显示分片配置 print("\n=== 分片配置 ==="); sh.getShardDistribution();
// 显示数据库分片状态 print("\n=== 数据库分片状态 ==="); sh.getShardDistribution("testdb"); EOF
echo "分片集群状态检查完成" }
add_shard() { local shard_name=$1 local shard_hosts=$2 echo "添加分片: $shard_name ($shard_hosts)..." mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 添加分片 // @author 运维实战
use admin;
// 添加分片 sh.addShard("$shard_name/$shard_hosts");
print("分片添加完成"); EOF
echo "分片添加完成" }
remove_shard() { local shard_name=$1 echo "移除分片: $shard_name..." mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 移除分片 // @author 运维实战
use admin;
// 开始移除分片 sh.removeShard("$shard_name");
// 等待数据迁移完成 while (sh.getBalancerState().inBalancerRound) { print("等待数据迁移完成..."); sleep(1000); }
print("分片移除完成"); EOF
echo "分片移除完成" }
enable_database_sharding() { local database=$1 echo "启用数据库分片: $database..." mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 启用数据库分片 // @author 运维实战
use admin;
// 启用数据库分片 sh.enableSharding("$database");
print("数据库分片启用完成"); EOF
echo "数据库分片启用完成" }
set_shard_key() { local database=$1 local collection=$2 local shard_key=$3 echo "设置分片键: $database.$collection ($shard_key)..." mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 设置分片键 // @author 运维实战
use admin;
// 设置分片键 sh.shardCollection("$database.$collection", $shard_key);
print("分片键设置完成"); EOF
echo "分片键设置完成" }
balance_shards() { echo "平衡分片..." mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 平衡分片 // @author 运维实战
use admin;
// 启用平衡器 sh.setBalancerState(true);
// 等待平衡完成 while (sh.getBalancerState().inBalancerRound) { print("等待分片平衡完成..."); sleep(1000); }
print("分片平衡完成"); EOF
echo "分片平衡完成" }
stop_balancer() { echo "停止平衡器..." mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 停止平衡器 // @author 运维实战
use admin;
// 停止平衡器 sh.setBalancerState(false);
print("平衡器停止完成"); EOF
echo "平衡器停止完成" }
main() { case $1 in "status") check_shard_cluster_status ;; "add") add_shard $2 $3 ;; "remove") remove_shard $2 ;; "enable") enable_database_sharding $2 ;; "shard") set_shard_key $2 $3 $4 ;; "balance") balance_shards ;; "stop-balancer") stop_balancer ;; *) echo "用法: $0 {status|add|remove|enable|shard|balance|stop-balancer}" echo " status - 检查分片集群状态" echo " add <shard_name> <shard_hosts> - 添加分片" echo " remove <shard_name> - 移除分片" echo " enable <database> - 启用数据库分片" echo " shard <database> <collection> <shard_key> - 设置分片键" echo " balance - 平衡分片" echo " stop-balancer - 停止平衡器" ;; esac }
main "$@"
|
4. MongoDB集群监控
4.1 集群监控脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
| #!/bin/bash
MONGO_PORT=27017 MONGOS_PORT=27019 ADMIN_USER="admin" ADMIN_PASS="admin123" LOG_FILE="/var/log/mongodb/monitor.log" ALERT_EMAIL="admin@example.com"
log_message() { local message=$1 echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> $LOG_FILE }
check_mongodb_status() { echo "检查MongoDB服务状态..." if mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin --eval "db.runCommand('ping')" > /dev/null 2>&1; then echo "主节点服务正常" log_message "主节点服务正常" else echo "主节点服务异常" log_message "主节点服务异常" send_alert "MongoDB主节点服务异常" fi if mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin --eval "db.runCommand('ping')" > /dev/null 2>&1; then echo "Mongos服务正常" log_message "Mongos服务正常" else echo "Mongos服务异常" log_message "Mongos服务异常" send_alert "MongoDB Mongos服务异常" fi }
check_replica_set_status() { echo "检查副本集状态..." mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 检查副本集状态 // @author 运维实战
use admin;
var status = rs.status(); var members = status.members;
for (var i = 0; i < members.length; i++) { var member = members[i]; var state = member.state; var name = member.name; if (state === 1) { print("主节点 " + name + " 状态正常"); } else if (state === 2) { print("从节点 " + name + " 状态正常"); } else { print("节点 " + name + " 状态异常: " + state); } }
// 检查复制延迟 var replicationInfo = rs.printSlaveReplicationInfo(); print("复制信息: " + replicationInfo); EOF
log_message "副本集状态检查完成" }
check_shard_cluster_status() { echo "检查分片集群状态..." mongo --port $MONGOS_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 检查分片集群状态 // @author 运维实战
use admin;
// 检查分片状态 var shardStatus = sh.status(); print("分片状态: " + shardStatus);
// 检查平衡器状态 var balancerState = sh.getBalancerState(); print("平衡器状态: " + balancerState);
// 检查分片分布 var shardDistribution = sh.getShardDistribution(); print("分片分布: " + shardDistribution); EOF
log_message "分片集群状态检查完成" }
check_database_performance() { echo "检查数据库性能..." mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF // 检查数据库性能 // @author 运维实战
use admin;
// 检查慢查询 var slowQueries = db.currentOp({"active": true, "secs_running": {"$gt": 5}}); print("慢查询数量: " + slowQueries.length);
// 检查连接数 var serverStatus = db.serverStatus(); var connections = serverStatus.connections; print("当前连接数: " + connections.current); print("可用连接数: " + connections.available);
// 检查内存使用 var mem = serverStatus.mem; print("内存使用: " + mem.resident + "MB");
// 检查索引使用 var indexStats = db.runCommand({"collStats": "users", "indexDetails": true}); print("索引统计: " + indexStats); EOF
log_message "数据库性能检查完成" }
check_disk_space() { echo "检查磁盘空间..." local data_dir="/data/mongodb" local disk_usage=$(df -h $data_dir | awk 'NR==2 {print $5}' | sed 's/%//') if [ $disk_usage -gt 80 ]; then echo "磁盘空间不足: $disk_usage%" log_message "磁盘空间不足: $disk_usage%" send_alert "MongoDB磁盘空间不足: $disk_usage%" else echo "磁盘空间正常: $disk_usage%" log_message "磁盘空间正常: $disk_usage%" fi }
check_log_files() { echo "检查日志文件..." local log_dir="/var/log/mongodb" local error_count=$(grep -c "ERROR" $log_dir/*.log 2>/dev/null || echo "0") local warning_count=$(grep -c "WARNING" $log_dir/*.log 2>/dev/null || echo "0") if [ $error_count -gt 0 ]; then echo "发现 $error_count 个错误日志" log_message "发现 $error_count 个错误日志" send_alert "MongoDB发现 $error_count 个错误日志" fi if [ $warning_count -gt 10 ]; then echo "发现 $warning_count 个警告日志" log_message "发现 $warning_count 个警告日志" send_alert "MongoDB发现 $warning_count 个警告日志" fi echo "日志检查完成" }
send_alert() { local message=$1 echo "发送告警: $message" echo "$message" | mail -s "MongoDB集群告警" $ALERT_EMAIL log_message "告警发送完成: $message" }
generate_monitor_report() { echo "生成监控报告..." local report_file="/var/log/mongodb/monitor_report_$(date +%Y%m%d).txt" cat > $report_file << EOF MongoDB集群监控报告 生成时间: $(date) ========================================
1. 服务状态检查 $(check_mongodb_status)
2. 副本集状态检查 $(check_replica_set_status)
3. 分片集群状态检查 $(check_shard_cluster_status)
4. 数据库性能检查 $(check_database_performance)
5. 磁盘空间检查 $(check_disk_space)
6. 日志文件检查 $(check_log_files)
======================================== EOF
echo "监控报告生成完成: $report_file" log_message "监控报告生成完成: $report_file" }
main() { echo "开始MongoDB集群监控..." check_mongodb_status check_replica_set_status check_shard_cluster_status check_database_performance check_disk_space check_log_files generate_monitor_report echo "MongoDB集群监控完成" }
main "$@"
|
5. 总结
5.1 MongoDB集群架构最佳实践
- 合理规划架构: 根据业务需求选择合适的集群架构
- 高可用设计: 使用副本集保证数据的高可用性
- 水平扩展: 使用分片集群实现数据的水平扩展
- 监控告警: 建立完善的监控和告警机制
- 备份恢复: 制定完善的备份和恢复策略
5.2 性能优化建议
- 索引优化: 合理创建和使用索引
- 查询优化: 优化查询语句和分片键
- 内存配置: 合理配置内存使用
- 网络优化: 优化网络配置和连接池
- 存储优化: 选择合适的存储引擎和压缩算法
5.3 运维管理要点
- 日常监控: 定期检查集群状态和性能
- 故障处理: 建立故障处理流程和应急预案
- 容量规划: 根据业务增长规划集群容量
- 安全加固: 加强集群安全配置和访问控制
- 文档管理: 维护完善的运维文档和操作手册
通过本文的MongoDB集群架构运维实战指南,您可以掌握MongoDB集群架构的设计、部署、监控和运维管理技巧,构建高可用、高性能的MongoDB集群系统!