1. MongoDB单节点只读硬件配置概述

MongoDB单节点只读4核8GB SSD50GB配置是专门用于读取密集型应用的标准配置,通过只读模式可以最大化读取性能,减少写入开销,是数据分析、报表查询、缓存预热等场景的理想选择。本文将详细介绍在这种硬件配置下的MongoDB只读节点部署、配置优化、性能调优以及运维管理的最佳实践。

1.1 硬件配置分析

1.1.1 硬件规格

  • CPU: 4核心处理器
  • 内存: 8GB RAM
  • 存储: 50GB SSD
  • 网络: 千兆网络
  • 节点类型: 单节点只读

1.1.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
#!/bin/bash
# MongoDB单节点只读资源分配策略
# @author 运维实战

echo "=== MongoDB单节点只读资源分配策略 ==="

cat << 'EOF'
资源分配策略:

1. 内存分配 (8GB总内存)
- 系统预留: 1.5GB (18.75%)
- MongoDB缓存: 5GB (62.5%)
- 操作系统缓存: 1.5GB (18.75%)

2. 存储分配 (50GB SSD)
- 系统分区: 8GB (16%)
- 数据分区: 35GB (70%)
- 日志分区: 7GB (14%)

3. CPU分配 (4核心)
- 系统进程: 0.5核心 (12.5%)
- MongoDB进程: 3核心 (75%)
- 其他服务: 0.5核心 (12.5%)

4. 网络分配
- 客户端连接: 70%
- 系统网络: 20%
- 预留带宽: 10%

5. 只读优化
- 禁用写入操作
- 优化读取缓存
- 减少锁竞争
- 提升查询性能
EOF

echo "资源分配策略说明完成"

1.2 只读节点架构设计

1.2.1 只读节点特点

  • 只读模式: 只处理读取操作,不处理写入操作
  • 高性能: 针对读取操作进行优化
  • 低延迟: 减少写入开销,提升查询响应速度
  • 高并发: 支持大量并发读取操作

1.2.2 应用场景

  • 数据分析: 大数据分析和报表查询
  • 缓存预热: 缓存数据预加载
  • 只读应用: 只读Web应用和API
  • 备份查询: 备份数据的查询和分析

2. 只读节点部署配置

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
#!/bin/bash
# MongoDB单节点只读系统环境准备脚本
# @author 运维实战

# 配置变量
MONGO_PORT=27017
DATA_DIR="/data/mongodb"
LOG_DIR="/var/log/mongodb"
CONFIG_DIR="/etc/mongodb"
ADMIN_USER="admin"
ADMIN_PASS="admin123"

# 系统优化配置
optimize_system_config() {
echo "优化系统配置..."

# 配置系统参数
cat > /etc/sysctl.conf << EOF
# MongoDB只读节点系统优化配置
# @author 运维实战

# 网络优化
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1

# 内存优化
vm.swappiness = 1
vm.dirty_ratio = 10
vm.dirty_background_ratio = 3
vm.overcommit_memory = 1
vm.vfs_cache_pressure = 50

# 文件系统优化
fs.file-max = 2097152
fs.aio-max-nr = 1048576
fs.inotify.max_user_watches = 1048576

# 只读优化
vm.drop_caches = 1
vm.page-cluster = 0
EOF

# 应用系统参数
sysctl -p

# 配置文件描述符限制
cat > /etc/security/limits.conf << EOF
# MongoDB只读节点文件描述符限制
# @author 运维实战

mongodb soft nofile 65535
mongodb hard nofile 65535
mongodb soft nproc 32768
mongodb hard nproc 32768
mongodb soft memlock unlimited
mongodb hard memlock unlimited
EOF

echo "系统配置优化完成"
}

# 创建目录结构
create_directories() {
echo "创建MongoDB只读节点目录结构..."

# 创建数据目录
mkdir -p $DATA_DIR
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

# 设置目录权限
chmod 755 $DATA_DIR
chmod 755 $LOG_DIR
chmod 755 $CONFIG_DIR

echo "目录结构创建完成"
}

# 配置SSD优化
configure_ssd_optimization() {
echo "配置SSD优化..."

# 检查SSD设备
local ssd_device=$(lsblk -d -o name,rota | grep -v "1" | head -1 | awk '{print $1}')

if [ -n "$ssd_device" ]; then
echo "检测到SSD设备: $ssd_device"

# 配置SSD调度器
echo noop > /sys/block/$ssd_device/queue/scheduler

# 配置SSD参数
echo 0 > /sys/block/$ssd_device/queue/rotational
echo 1 > /sys/block/$ssd_device/queue/nomerges
echo 512 > /sys/block/$ssd_device/queue/nr_requests

# 配置TRIM支持
systemctl enable fstrim.timer
systemctl start fstrim.timer

# 配置SSD只读优化
echo 1 > /sys/block/$ssd_device/queue/add_random
echo 0 > /sys/block/$ssd_device/queue/iostats

echo "SSD优化配置完成"
else
echo "未检测到SSD设备,跳过SSD优化"
fi
}

# 配置内存优化
configure_memory_optimization() {
echo "配置内存优化..."

# 配置透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 配置内存分配策略
echo 1 > /proc/sys/vm/overcommit_memory
echo 1 > /proc/sys/vm/swappiness

# 配置内存回收
echo 3 > /proc/sys/vm/dirty_background_ratio
echo 10 > /proc/sys/vm/dirty_ratio

# 配置只读内存优化
echo 1 > /proc/sys/vm/drop_caches
echo 0 > /proc/sys/vm/page-cluster

echo "内存优化配置完成"
}

# 配置只读优化
configure_readonly_optimization() {
echo "配置只读优化..."

# 配置文件系统只读优化
local data_partition=$(df $DATA_DIR | awk 'NR==2 {print $1}')

if [ -n "$data_partition" ]; then
# 重新挂载为只读优化
mount -o remount,noatime,nodiratime $data_partition $DATA_DIR

# 配置文件系统参数
tune2fs -o journal_data_writeback $data_partition 2>/dev/null || true
fi

# 配置内核只读优化
echo 1 > /proc/sys/vm/drop_caches
echo 0 > /proc/sys/vm/page-cluster

echo "只读优化配置完成"
}

# 主函数
main() {
echo "开始MongoDB单节点只读系统环境准备..."

optimize_system_config
create_directories
configure_ssd_optimization
configure_memory_optimization
configure_readonly_optimization

echo "MongoDB单节点只读系统环境准备完成!"
}

# 执行主函数
main "$@"

2.2 MongoDB只读配置文件生成

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
#!/bin/bash
# MongoDB单节点只读配置文件生成脚本
# @author 运维实战

# 配置变量
MONGO_PORT=27017
DATA_DIR="/data/mongodb"
LOG_DIR="/var/log/mongodb"
CONFIG_DIR="/etc/mongodb"

# 生成只读节点配置文件
generate_readonly_config() {
echo "生成MongoDB只读节点配置文件..."

cat > $CONFIG_DIR/mongod-readonly.conf << EOF
# MongoDB只读节点配置文件 (4核8GB SSD50GB)
# @author 运维实战

# 存储配置
storage:
dbPath: $DATA_DIR
journal:
enabled: false
commitIntervalMs: 100
wiredTiger:
engineConfig:
cacheSizeGB: 5
journalCompressor: snappy
directoryForIndexes: true
eviction: (threads_min=3,threads_max=6)
checkpoint: (wait=120,log_size=2GB)
collectionConfig:
blockCompressor: snappy
indexConfig:
prefixCompression: true
logConfig:
compressor: snappy
file_max: 2GB

# 网络配置
net:
port: $MONGO_PORT
bindIp: 0.0.0.0
maxIncomingConnections: 1000
compression:
compressors: snappy,zstd
serviceExecutor: adaptive
wireObjectCheck: false

# 日志配置
systemLog:
destination: file
path: $LOG_DIR/mongod-readonly.log
logAppend: true
logRotate: reopen
verbosity: 1
component:
accessControl:
verbosity: 1
command:
verbosity: 1
query:
verbosity: 1

# 进程管理
processManagement:
fork: true
pidFilePath: $DATA_DIR/mongod.pid
timeZoneInfo: /usr/share/zoneinfo

# 安全配置
security:
authorization: enabled
keyFile: $CONFIG_DIR/keyfile

# 性能优化
operationProfiling:
slowOpThresholdMs: 50
mode: slowOp

# 监控配置
setParameter:
enableLocalhostAuthBypass: false
logLevel: 1
maxConns: 1000
connPoolMaxShardedConnsPerHost: 200
connPoolMaxConnsPerHost: 200
wiredTigerConcurrentReadTransactions: 128
wiredTigerConcurrentWriteTransactions: 0
wiredTigerEngineRuntimeConfig: "cache_size=5GB,eviction=(threads_min=3,threads_max=6)"

# 只读优化参数
readOnly: true
queryExecutor: "classic"
enableFreeMonitoring: false
diagnosticDataCollectionEnabled: false

# 索引优化
maxIndexBuildMemoryUsageMegabytes: 1024
backgroundIndexBuildRetry: true

# 缓存优化
wiredTigerCacheSizeGB: 5
wiredTigerCacheOverflowSizeGB: 1
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 "密钥文件生成完成"
}

# 生成启动脚本
generate_startup_script() {
echo "生成MongoDB启动脚本..."

cat > /etc/systemd/system/mongodb-readonly.service << EOF
[Unit]
Description=MongoDB Read-Only Node
After=network.target

[Service]
Type=forking
User=mongodb
Group=mongodb
ExecStart=/usr/bin/mongod --config $CONFIG_DIR/mongod-readonly.conf
ExecReload=/bin/kill -HUP \$MAINPID
ExecStop=/bin/kill -TERM \$MAINPID
PIDFile=$DATA_DIR/mongod.pid
LimitNOFILE=65535
LimitNPROC=32768
LimitMEMLOCK=unlimited

[Install]
WantedBy=multi-user.target
EOF

# 重新加载systemd配置
systemctl daemon-reload
systemctl enable mongodb-readonly.service

echo "启动脚本生成完成"
}

# 主函数
main() {
echo "开始生成MongoDB单节点只读配置文件..."

generate_readonly_config
generate_keyfile
generate_startup_script

echo "MongoDB单节点只读配置文件生成完成!"
}

# 执行主函数
main "$@"

2.3 只读节点部署脚本

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
#!/bin/bash
# MongoDB单节点只读部署脚本
# @author 运维实战

# 配置变量
MONGO_PORT=27017
DATA_DIR="/data/mongodb"
LOG_DIR="/var/log/mongodb"
CONFIG_DIR="/etc/mongodb"
ADMIN_USER="admin"
ADMIN_PASS="admin123"

# 启动MongoDB只读服务
start_mongodb_readonly() {
echo "启动MongoDB只读节点服务..."

# 使用systemd启动服务
systemctl start mongodb-readonly.service
sleep 5

# 检查服务状态
if systemctl is-active --quiet mongodb-readonly.service; then
echo "MongoDB只读节点服务启动成功"
else
echo "MongoDB只读节点服务启动失败"
systemctl status mongodb-readonly.service
exit 1
fi
}

# 创建用户账户
create_users() {
echo "创建MongoDB用户账户..."

# 等待服务稳定
sleep 10

# 创建管理员用户
mongo --port $MONGO_PORT << EOF
// 创建MongoDB用户账户
// @author 运维实战

use admin;

// 创建管理员用户
db.createUser({
user: "$ADMIN_USER",
pwd: "$ADMIN_PASS",
roles: [
{ role: "root", db: "admin" },
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" }
]
});

// 创建只读用户
use appdb;
db.createUser({
user: "readonly",
pwd: "read123",
roles: [
{ role: "read", db: "appdb" }
]
});

// 创建分析用户
use analytics;
db.createUser({
user: "analyst",
pwd: "analyst123",
roles: [
{ role: "read", db: "analytics" },
{ role: "read", db: "appdb" }
]
});

print("用户账户创建完成");
EOF

echo "用户账户创建完成"
}

# 配置只读优化
configure_readonly_optimization() {
echo "配置只读优化..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 配置只读优化
// @author 运维实战

use admin;

// 设置只读模式
db.adminCommand({setParameter: 1, readOnly: true});

// 配置读取偏好
db.getMongo().setReadPref("primaryPreferred");

// 配置读取关注
db.getMongo().setReadConcern("majority");

// 禁用写入操作
db.adminCommand({setParameter: 1, enableFreeMonitoring: false});
db.adminCommand({setParameter: 1, diagnosticDataCollectionEnabled: false});

// 优化查询执行器
db.adminCommand({setParameter: 1, queryExecutor: "classic"});

// 配置缓存优化
db.adminCommand({
setParameter: 1,
wiredTigerEngineRuntimeConfig: "cache_size=5GB,eviction=(threads_min=3,threads_max=6)"
});

print("只读优化配置完成");
EOF

echo "只读优化配置完成"
}

# 导入测试数据
import_test_data() {
echo "导入测试数据..."

# 创建测试数据库和集合
mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 导入测试数据
// @author 运维实战

use testdb;

// 创建测试集合
db.createCollection("users");
db.createCollection("products");
db.createCollection("orders");

// 插入测试数据
for (var i = 1; i <= 1000; i++) {
db.users.insert({
userId: i,
username: "user" + i,
email: "user" + i + "@example.com",
age: Math.floor(Math.random() * 50) + 18,
city: ["Beijing", "Shanghai", "Guangzhou", "Shenzhen"][Math.floor(Math.random() * 4)],
createdAt: new Date()
});
}

for (var i = 1; i <= 500; i++) {
db.products.insert({
productId: i,
name: "Product " + i,
category: ["Electronics", "Clothing", "Books", "Home"][Math.floor(Math.random() * 4)],
price: Math.floor(Math.random() * 1000) + 10,
stock: Math.floor(Math.random() * 100),
createdAt: new Date()
});
}

for (var i = 1; i <= 2000; i++) {
db.orders.insert({
orderId: i,
userId: Math.floor(Math.random() * 1000) + 1,
productId: Math.floor(Math.random() * 500) + 1,
quantity: Math.floor(Math.random() * 5) + 1,
total: Math.floor(Math.random() * 1000) + 10,
status: ["pending", "completed", "cancelled"][Math.floor(Math.random() * 3)],
createdAt: new Date()
});
}

// 创建索引
db.users.createIndex({userId: 1});
db.users.createIndex({username: 1});
db.users.createIndex({email: 1});
db.users.createIndex({city: 1});

db.products.createIndex({productId: 1});
db.products.createIndex({category: 1});
db.products.createIndex({price: 1});

db.orders.createIndex({orderId: 1});
db.orders.createIndex({userId: 1});
db.orders.createIndex({productId: 1});
db.orders.createIndex({status: 1});
db.orders.createIndex({createdAt: 1});

print("测试数据导入完成");
EOF

echo "测试数据导入完成"
}

# 验证部署结果
verify_deployment() {
echo "验证MongoDB只读节点部署结果..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 验证MongoDB只读节点部署结果
// @author 运维实战

use admin;

// 检查服务器状态
print("=== 只读节点部署验证 ===");
var serverStatus = db.serverStatus();
print("服务器状态: " + serverStatus.ok);

// 检查只读模式
print("\n=== 只读模式检查 ===");
var readOnlyStatus = db.adminCommand({getParameter: 1, readOnly: 1});
print("只读模式: " + readOnlyStatus.readOnly);

// 检查内存使用情况
print("\n=== 内存使用情况 ===");
print("物理内存: " + serverStatus.mem.resident + " MB");
print("虚拟内存: " + serverStatus.mem.virtual + " MB");
print("映射内存: " + serverStatus.mem.mapped + " MB");

// 检查连接情况
print("\n=== 连接情况 ===");
print("当前连接数: " + serverStatus.connections.current);
print("可用连接数: " + serverStatus.connections.available);
print("总连接数: " + serverStatus.connections.totalCreated);

// 检查存储情况
print("\n=== 存储情况 ===");
print("数据大小: " + serverStatus.storageSize);
print("索引大小: " + serverStatus.indexSize);
print("总大小: " + (serverStatus.storageSize + serverStatus.indexSize));

// 检查测试数据
print("\n=== 测试数据检查 ===");
use testdb;
print("用户数量: " + db.users.count());
print("产品数量: " + db.products.count());
print("订单数量: " + db.orders.count());

// 检查索引
print("\n=== 索引检查 ===");
print("用户索引: " + db.users.getIndexes().length);
print("产品索引: " + db.products.getIndexes().length);
print("订单索引: " + db.orders.getIndexes().length);

// 测试只读操作
print("\n=== 只读操作测试 ===");
var user = db.users.findOne();
print("查询用户: " + user.username);

var product = db.products.findOne();
print("查询产品: " + product.name);

var order = db.orders.findOne();
print("查询订单: " + order.orderId);

print("\n只读节点部署验证完成");
EOF

echo "只读节点部署验证完成"
}

# 主函数
main() {
echo "开始部署MongoDB单节点只读..."

start_mongodb_readonly
create_users
configure_readonly_optimization
import_test_data
verify_deployment

echo "MongoDB单节点只读部署完成!"
echo "只读节点: localhost:$MONGO_PORT"
echo "管理员用户: $ADMIN_USER"
echo "管理员密码: $ADMIN_PASS"
echo "只读用户: readonly"
echo "只读密码: read123"
}

# 执行主函数
main "$@"

3. 性能优化配置

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
#!/bin/bash
# MongoDB单节点只读性能优化脚本
# @author 运维实战

# 配置变量
MONGO_PORT=27017
ADMIN_USER="admin"
ADMIN_PASS="admin123"

# 优化内存配置
optimize_memory_config() {
echo "优化内存配置..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 优化内存配置
// @author 运维实战

use admin;

// 获取当前内存配置
var serverStatus = db.serverStatus();
print("当前内存使用情况:");
print(" 物理内存: " + serverStatus.mem.resident + " MB");
print(" 虚拟内存: " + serverStatus.mem.virtual + " MB");
print(" 映射内存: " + serverStatus.mem.mapped + " MB");

// 配置WiredTiger缓存 (5GB for 8GB RAM)
db.adminCommand({
setParameter: 1,
wiredTigerEngineRuntimeConfig: "cache_size=5GB,eviction=(threads_min=3,threads_max=6)"
});

// 配置连接池
db.adminCommand({
setParameter: 1,
maxConns: 1000,
connPoolMaxShardedConnsPerHost: 200,
connPoolMaxConnsPerHost: 200
});

// 配置并发事务 (只读优化)
db.adminCommand({
setParameter: 1,
wiredTigerConcurrentReadTransactions: 128,
wiredTigerConcurrentWriteTransactions: 0
});

// 配置缓存溢出
db.adminCommand({
setParameter: 1,
wiredTigerCacheOverflowSizeGB: 1
});

print("内存配置优化完成");
EOF

echo "内存配置优化完成"
}

# 优化存储配置
optimize_storage_config() {
echo "优化存储配置..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 优化存储配置
// @author 运维实战

use admin;

// 配置WiredTiger存储引擎
db.adminCommand({
setParameter: 1,
wiredTigerEngineRuntimeConfig: "cache_size=5GB,eviction=(threads_min=3,threads_max=6),checkpoint=(wait=120,log_size=2GB)"
});

// 配置压缩
db.adminCommand({
setParameter: 1,
wiredTigerCollectionBlockCompressor: "snappy",
wiredTigerIndexPrefixCompression: true
});

// 配置日志
db.adminCommand({
setParameter: 1,
wiredTigerLogCompressor: "snappy",
wiredTigerLogFileMax: "2GB"
});

// 禁用写入相关配置
db.adminCommand({
setParameter: 1,
wiredTigerJournalCompressor: "snappy"
});

print("存储配置优化完成");
EOF

echo "存储配置优化完成"
}

# 优化网络配置
optimize_network_config() {
echo "优化网络配置..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 优化网络配置
// @author 运维实战

use admin;

// 配置网络参数
db.adminCommand({
setParameter: 1,
maxIncomingConnections: 1000,
connPoolMaxShardedConnsPerHost: 200,
connPoolMaxConnsPerHost: 200
});

// 配置压缩
db.adminCommand({
setParameter: 1,
networkMessageCompressors: "snappy,zstd"
});

// 配置超时
db.adminCommand({
setParameter: 1,
socketTimeoutMS: 30000,
connectTimeoutMS: 10000
});

// 配置只读网络优化
db.adminCommand({
setParameter: 1,
wireObjectCheck: false
});

print("网络配置优化完成");
EOF

echo "网络配置优化完成"
}

# 优化查询配置
optimize_query_config() {
echo "优化查询配置..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 优化查询配置
// @author 运维实战

use admin;

// 配置查询执行器
db.adminCommand({
setParameter: 1,
queryExecutor: "classic"
});

// 配置索引构建
db.adminCommand({
setParameter: 1,
maxIndexBuildMemoryUsageMegabytes: 1024
});

// 配置后台索引构建
db.adminCommand({
setParameter: 1,
backgroundIndexBuildRetry: true
});

// 配置查询优化
db.adminCommand({
setParameter: 1,
internalQueryExecMaxBlockingSortBytes: 33554432
});

// 配置聚合优化
db.adminCommand({
setParameter: 1,
internalQueryExecMaxBlockingSortBytes: 33554432
});

print("查询配置优化完成");
EOF

echo "查询配置优化完成"
}

# 优化只读配置
optimize_readonly_config() {
echo "优化只读配置..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 优化只读配置
// @author 运维实战

use admin;

// 设置只读模式
db.adminCommand({setParameter: 1, readOnly: true});

// 禁用写入相关功能
db.adminCommand({setParameter: 1, enableFreeMonitoring: false});
db.adminCommand({setParameter: 1, diagnosticDataCollectionEnabled: false});

// 配置读取偏好
db.getMongo().setReadPref("primaryPreferred");

// 配置读取关注
db.getMongo().setReadConcern("majority");

// 优化缓存策略
db.adminCommand({
setParameter: 1,
wiredTigerEngineRuntimeConfig: "cache_size=5GB,eviction=(threads_min=3,threads_max=6),checkpoint=(wait=120)"
});

print("只读配置优化完成");
EOF

echo "只读配置优化完成"
}

# 验证性能优化效果
verify_performance_optimization() {
echo "验证性能优化效果..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 验证性能优化效果
// @author 运维实战

use admin;

// 获取服务器状态
var serverStatus = db.serverStatus();
print("=== 性能优化效果验证 ===");

// 内存使用情况
print("内存使用情况:");
print(" 物理内存: " + serverStatus.mem.resident + " MB");
print(" 虚拟内存: " + serverStatus.mem.virtual + " MB");
print(" 映射内存: " + serverStatus.mem.mapped + " MB");

// 连接情况
print("\n连接情况:");
print(" 当前连接数: " + serverStatus.connections.current);
print(" 可用连接数: " + serverStatus.connections.available);
print(" 总连接数: " + serverStatus.connections.totalCreated);

// 网络情况
print("\n网络情况:");
print(" 字节输入: " + serverStatus.network.bytesIn);
print(" 字节输出: " + serverStatus.network.bytesOut);
print(" 请求数: " + serverStatus.network.numRequests);

// 存储情况
print("\n存储情况:");
print(" 数据大小: " + serverStatus.storageSize);
print(" 索引大小: " + serverStatus.indexSize);
print(" 总大小: " + (serverStatus.storageSize + serverStatus.indexSize));

// 只读模式检查
print("\n只读模式检查:");
var readOnlyStatus = db.adminCommand({getParameter: 1, readOnly: 1});
print(" 只读模式: " + readOnlyStatus.readOnly);

// 检查性能阈值
var connections = serverStatus.connections;
if (connections.current > 800) {
print("警告: 连接数过高: " + connections.current);
}

var memory = serverStatus.mem;
if (memory.resident > 7000) {
print("警告: 内存使用过高: " + memory.resident + " MB");
}

print("\n性能优化效果验证完成");
EOF

echo "性能优化效果验证完成"
}

# 主函数
main() {
echo "开始MongoDB单节点只读性能优化..."

optimize_memory_config
optimize_storage_config
optimize_network_config
optimize_query_config
optimize_readonly_config
verify_performance_optimization

echo "MongoDB单节点只读性能优化完成!"
}

# 执行主函数
main "$@"

4. 监控和运维管理

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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#!/bin/bash
# MongoDB单节点只读监控脚本
# @author 运维实战

# 配置变量
MONGO_PORT=27017
ADMIN_USER="admin"
ADMIN_PASS="admin123"
LOG_FILE="/var/log/mongodb/readonly_monitor.log"
ALERT_EMAIL="admin@example.com"

# 记录日志
log_message() {
local message=$1
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> $LOG_FILE
}

# 监控只读节点状态
monitor_readonly_status() {
echo "监控只读节点状态..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 监控只读节点状态
// @author 运维实战

use admin;

// 获取服务器状态
var serverStatus = db.serverStatus();

print("=== 只读节点状态监控 ===");
print("服务器状态: " + serverStatus.ok);

// 检查只读模式
var readOnlyStatus = db.adminCommand({getParameter: 1, readOnly: 1});
print("只读模式: " + readOnlyStatus.readOnly);

// 检查内存使用情况
print("\n=== 内存使用情况 ===");
print("物理内存: " + serverStatus.mem.resident + " MB");
print("虚拟内存: " + serverStatus.mem.virtual + " MB");
print("映射内存: " + serverStatus.mem.mapped + " MB");

// 检查连接情况
print("\n=== 连接情况 ===");
print("当前连接数: " + serverStatus.connections.current);
print("可用连接数: " + serverStatus.connections.available);
print("总连接数: " + serverStatus.connections.totalCreated);

// 检查网络情况
print("\n=== 网络情况 ===");
print("字节输入: " + serverStatus.network.bytesIn);
print("字节输出: " + serverStatus.network.bytesOut);
print("请求数: " + serverStatus.network.numRequests);

// 检查存储情况
print("\n=== 存储情况 ===");
print("数据大小: " + serverStatus.storageSize);
print("索引大小: " + serverStatus.indexSize);
print("总大小: " + (serverStatus.storageSize + serverStatus.indexSize));

// 检查操作情况
print("\n=== 操作情况 ===");
print("查询操作: " + serverStatus.opcounters.query);
print("插入操作: " + serverStatus.opcounters.insert);
print("更新操作: " + serverStatus.opcounters.update);
print("删除操作: " + serverStatus.opcounters.delete);

// 检查性能指标
print("\n=== 性能指标 ===");
print("平均查询时间: " + serverStatus.opcounters.query + " queries");
print("缓存命中率: " + serverStatus.wiredTiger.cache["bytes currently in the cache"]);

// 检查阈值
if (serverStatus.connections.current > 800) {
print("警告: 连接数过高: " + serverStatus.connections.current);
}

if (serverStatus.mem.resident > 7000) {
print("警告: 内存使用过高: " + serverStatus.mem.resident + " MB");
}

if (serverStatus.opcounters.insert > 0) {
print("警告: 检测到写入操作: " + serverStatus.opcounters.insert);
}
EOF

log_message "只读节点状态监控完成"
}

# 监控查询性能
monitor_query_performance() {
echo "监控查询性能..."

mongo --port $MONGO_PORT -u $ADMIN_USER -p $ADMIN_PASS --authenticationDatabase admin << EOF
// 监控查询性能
// @author 运维实战

use testdb;

// 执行性能测试查询
print("=== 查询性能监控 ===");

// 简单查询测试
var startTime = new Date();
var users = db.users.find({city: "Beijing"}).limit(100).toArray();
var endTime = new Date();
print("简单查询耗时: " + (endTime - startTime) + " ms, 结果数: " + users.length);

// 索引查询测试
startTime = new Date();
var products = db.products.find({category: "Electronics", price: {\$gte: 100}}).limit(50).toArray();
endTime = new Date();
print("索引查询耗时: " + (endTime - startTime) + " ms, 结果数: " + products.length);

// 聚合查询测试
startTime = new Date();
var orders = db.orders.aggregate([
{\$match: {status: "completed"}},
{\$group: {_id: "\$userId", total: {\$sum: "\$total"}}},
{\$sort: {total: -1}},
{\$limit: 10}
]).toArray();
endTime = new Date();
print("聚合查询耗时: " + (endTime - startTime) + " ms, 结果数: " + orders.length);

// 复杂查询测试
startTime = new Date();
var complexQuery = db.orders.aggregate([
{\$lookup: {
from: "users",
localField: "userId",
foreignField: "userId",
as: "user"
}},
{\$lookup: {
from: "products",
localField: "productId",
foreignField: "productId",
as: "product"
}},
{\$unwind: "\$user"},
{\$unwind: "\$product"},
{\$match: {"user.city": "Beijing"}},
{\$group: {_id: "\$product.category", total: {\$sum: "\$total"}}},
{\$sort: {total: -1}}
]).toArray();
endTime = new Date();
print("复杂查询耗时: " + (endTime - startTime) + " ms, 结果数: " + complexQuery.length);

print("查询性能监控完成");
EOF

log_message "查询性能监控完成"
}

# 监控磁盘空间
monitor_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
}

# 监控日志文件
monitor_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")
local slow_query_count=$(grep -c "slow operation" $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

if [ $slow_query_count -gt 5 ]; then
echo "发现 $slow_query_count 个慢查询"
log_message "发现 $slow_query_count 个慢查询"
send_alert "MongoDB只读节点发现 $slow_query_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/readonly_monitor_report_$(date +%Y%m%d).txt"

cat > $report_file << EOF
MongoDB单节点只读监控报告
生成时间: $(date)
硬件配置: 4核8GB SSD50GB
========================================

1. 只读节点状态监控
$(monitor_readonly_status)

2. 查询性能监控
$(monitor_query_performance)

3. 磁盘空间监控
$(monitor_disk_space)

4. 日志文件监控
$(monitor_log_files)

========================================
EOF

echo "监控报告生成完成: $report_file"
log_message "监控报告生成完成: $report_file"
}

# 主函数
main() {
echo "开始MongoDB单节点只读监控..."

monitor_readonly_status
monitor_query_performance
monitor_disk_space
monitor_log_files
generate_monitor_report

echo "MongoDB单节点只读监控完成"
}

# 执行主函数
main "$@"

5. 总结

5.1 MongoDB单节点只读最佳实践

  1. 硬件配置优化: 合理分配4核8GB内存和50GB SSD存储
  2. 资源分配策略: 系统预留1.5GB,MongoDB使用5GB,缓存1.5GB
  3. 只读优化: 禁用写入操作,优化读取缓存,减少锁竞争
  4. 存储优化: 利用SSD高性能特性,配置合适的压缩和日志
  5. 监控告警: 建立完善的监控和告警机制

5.2 性能优化建议

  • 内存配置: 5GB WiredTiger缓存,128个并发读事务
  • 存储配置: Snappy压缩,2GB日志文件,120秒检查点
  • 网络配置: 1000个最大连接,Snappy/Zstd压缩
  • 查询优化: 经典查询执行器,1024MB索引构建内存
  • 只读优化: 禁用写入功能,优化缓存策略

5.3 运维管理要点

  • 日常监控: 定期检查只读节点状态和查询性能
  • 容量管理: 监控磁盘空间使用,及时清理日志
  • 性能调优: 根据查询模式优化索引和缓存
  • 安全加固: 加强访问控制和用户权限管理
  • 备份策略: 制定数据备份和恢复策略

通过本文的MongoDB单节点只读4核8GB SSD50GB运维实战指南,您可以掌握在这种硬件配置下的MongoDB只读节点部署、配置优化、性能调优以及运维管理的最佳实践,构建高性能、稳定的MongoDB只读查询系统!