1. MongoDB集群架构概述

MongoDB集群架构是构建高可用、高性能、可扩展数据库系统的核心技术。通过合理的集群架构设计,可以实现数据的高可用性、负载均衡、水平扩展等功能。本文将详细介绍MongoDB集群架构的各种类型、部署方法、运维管理技巧以及在企业级应用中的最佳实践。

1.1 集群架构的核心价值

  1. 高可用性: 通过副本集实现数据冗余和故障转移
  2. 水平扩展: 通过分片集群实现数据的水平扩展
  3. 负载均衡: 通过分片实现读写负载的分散
  4. 数据安全: 通过多副本保证数据的安全性
  5. 性能优化: 通过集群架构提升整体性能

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
# MongoDB副本集部署脚本
# @author 运维实战

# 配置变量
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

# 从节点1配置
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

# 从节点2配置
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 "密钥文件生成完成"
}

# 启动MongoDB服务
start_mongodb() {
echo "启动MongoDB服务..."

# 启动主节点
mongod --config $CONFIG_DIR/mongod-primary.conf
sleep 5

# 启动从节点1
mongod --config $CONFIG_DIR/mongod-secondary1.conf
sleep 5

# 启动从节点2
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
# MongoDB副本集管理脚本
# @author 运维实战

# 配置变量
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
# MongoDB分片集群部署脚本
# @author 运维实战

# 配置变量
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 "生成分片集群配置文件..."

# 分片0主节点配置
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

# Mongos配置
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
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
# MongoDB分片集群管理脚本
# @author 运维实战

# 配置变量
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
# MongoDB集群监控脚本
# @author 运维实战

# 配置变量
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
}

# 检查MongoDB服务状态
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

# 检查Mongos状态
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

# 发送短信告警(需要配置短信服务)
# curl -X POST "https://api.sms.com/send" -d "message=$message"

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集群架构最佳实践

  1. 合理规划架构: 根据业务需求选择合适的集群架构
  2. 高可用设计: 使用副本集保证数据的高可用性
  3. 水平扩展: 使用分片集群实现数据的水平扩展
  4. 监控告警: 建立完善的监控和告警机制
  5. 备份恢复: 制定完善的备份和恢复策略

5.2 性能优化建议

  • 索引优化: 合理创建和使用索引
  • 查询优化: 优化查询语句和分片键
  • 内存配置: 合理配置内存使用
  • 网络优化: 优化网络配置和连接池
  • 存储优化: 选择合适的存储引擎和压缩算法

5.3 运维管理要点

  • 日常监控: 定期检查集群状态和性能
  • 故障处理: 建立故障处理流程和应急预案
  • 容量规划: 根据业务增长规划集群容量
  • 安全加固: 加强集群安全配置和访问控制
  • 文档管理: 维护完善的运维文档和操作手册

通过本文的MongoDB集群架构运维实战指南,您可以掌握MongoDB集群架构的设计、部署、监控和运维管理技巧,构建高可用、高性能的MongoDB集群系统!