1. Redis运维监控概述

Redis作为高性能的内存数据库,在生产环境中需要专业的运维监控和优化。本文将详细介绍Redis性能监控、内存优化、集群管理、故障诊断的完整解决方案,帮助运维人员有效管理Redis服务。

1.1 核心挑战

  1. 性能监控: 实时监控Redis性能指标
  2. 内存管理: 优化Redis内存使用和回收
  3. 集群管理: 管理Redis集群和主从复制
  4. 故障诊断: 快速定位和解决Redis问题
  5. 数据安全: 保障Redis数据安全和备份

1.2 技术架构

1
2
3
4
5
Redis监控 → 数据采集 → 性能分析 → 告警通知 → 自动优化
↓ ↓ ↓ ↓ ↓
性能指标 → 监控代理 → 数据存储 → 告警引擎 → 调优脚本
↓ ↓ ↓ ↓ ↓
集群管理 → 健康检查 → 故障诊断 → 自动修复 → 运维记录

2. Redis监控系统

2.1 Maven依赖配置

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
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Boot Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>

<!-- Lettuce -->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>

<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
</dependencies>

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
# application.yml
server:
port: 8080

spring:
redis:
host: localhost
port: 6379
database: 0
timeout: 5000
lettuce:
pool:
max-active: 200
max-idle: 20
min-idle: 5

# Redis监控配置
redis-monitor:
collection-interval: 5000 # 采集间隔(毫秒)
memory-alert-threshold: 85 # 内存告警阈值(%)
memory-critical-threshold: 95 # 内存严重告警阈值(%)
connection-alert-threshold: 1000 # 连接数告警阈值
slow-log-threshold: 100 # 慢查询告警阈值(ms)
cluster-monitor-enabled: true # 启用集群监控

3. Redis监控服务

3.1 Redis监控实体类

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
/**
* Redis监控数据实体类
*/
@Data
@TableName("redis_monitor_data")
public class RedisMonitorData {

@TableId(type = IdType.AUTO)
private Long id; // 主键ID

private String hostname; // 主机名

private String ip; // IP地址

private Integer port; // 端口

private String redisVersion; // Redis版本

private String redisMode; // Redis模式

private Long usedMemory; // 已使用内存

private Long maxMemory; // 最大内存

private Double memoryUsage; // 内存使用率

private Long connectedClients; // 连接客户端数

private Long totalCommandsProcessed; // 总处理命令数

private Long instantaneousOpsPerSec; // 每秒操作数

private Long keyspaceHits; // 键空间命中数

private Long keyspaceMisses; // 键空间未命中数

private Double hitRate; // 命中率

private Long expiredKeys; // 过期键数

private Long evictedKeys; // 驱逐键数

private Long slowLogCount; // 慢查询数量

private String replicationRole; // 复制角色

private String masterHost; // 主节点主机

private Integer masterPort; // 主节点端口

private Long masterLinkStatus; // 主链接状态

private Date collectTime; // 采集时间

private Date createTime; // 创建时间
}

/**
* Redis集群节点实体类
*/
@Data
@TableName("redis_cluster_node")
public class RedisClusterNode {

@TableId(type = IdType.AUTO)
private Long id; // 主键ID

private String nodeId; // 节点ID

private String hostname; // 主机名

private String ip; // IP地址

private Integer port; // 端口

private String nodeRole; // 节点角色

private String nodeState; // 节点状态

private String masterNodeId; // 主节点ID

private Integer slotStart; // 槽位开始

private Integer slotEnd; // 槽位结束

private Long connectedClients; // 连接客户端数

private Long usedMemory; // 已使用内存

private String nodeFlags; // 节点标志

private Date lastHeartbeat; // 最后心跳

private Date createTime; // 创建时间
}

3.2 Redis监控服务

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
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/**
* Redis监控服务
* 负责Redis数据的采集、存储和分析
*/
@Service
public class RedisMonitorService {

@Autowired
private RedisMonitorDataMapper redisMonitorDataMapper;

@Autowired
private RedisClusterNodeMapper redisClusterNodeMapper;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Autowired
private AlertService alertService;

@Autowired
private JedisPool jedisPool;

/**
* 采集Redis数据
* 定期采集Redis性能指标
*/
@Scheduled(fixedRate = 5000) // 每5秒执行一次
public void collectRedisData() {
try {
// 1. 获取Redis信息
RedisInfo redisInfo = getRedisInfo();

// 2. 创建Redis监控数据
RedisMonitorData monitorData = createRedisMonitorData(redisInfo);

// 3. 保存到数据库
redisMonitorDataMapper.insert(monitorData);

// 4. 更新缓存
updateRedisCache(monitorData);

// 5. 检查Redis告警
checkRedisAlert(monitorData);

log.debug("采集Redis数据: hostname={}, memoryUsage={}%, hitRate={}%",
monitorData.getHostname(), monitorData.getMemoryUsage(), monitorData.getHitRate());

} catch (Exception e) {
log.error("采集Redis数据失败: {}", e.getMessage(), e);
}
}

/**
* 获取Redis信息
*/
private RedisInfo getRedisInfo() {
RedisInfo redisInfo = new RedisInfo();

try (Jedis jedis = jedisPool.getResource()) {
// 获取Redis服务器信息
String info = jedis.info();
Map<String, String> infoMap = parseRedisInfo(info);

// 设置基本信息
redisInfo.setRedisVersion(infoMap.get("redis_version"));
redisInfo.setRedisMode(infoMap.get("redis_mode"));
redisInfo.setUsedMemory(Long.parseLong(infoMap.getOrDefault("used_memory", "0")));
redisInfo.setMaxMemory(Long.parseLong(infoMap.getOrDefault("maxmemory", "0")));
redisInfo.setConnectedClients(Long.parseLong(infoMap.getOrDefault("connected_clients", "0")));
redisInfo.setTotalCommandsProcessed(Long.parseLong(infoMap.getOrDefault("total_commands_processed", "0")));
redisInfo.setInstantaneousOpsPerSec(Long.parseLong(infoMap.getOrDefault("instantaneous_ops_per_sec", "0")));
redisInfo.setKeyspaceHits(Long.parseLong(infoMap.getOrDefault("keyspace_hits", "0")));
redisInfo.setKeyspaceMisses(Long.parseLong(infoMap.getOrDefault("keyspace_misses", "0")));
redisInfo.setExpiredKeys(Long.parseLong(infoMap.getOrDefault("expired_keys", "0")));
redisInfo.setEvictedKeys(Long.parseLong(infoMap.getOrDefault("evicted_keys", "0")));

// 计算内存使用率
if (redisInfo.getMaxMemory() > 0) {
redisInfo.setMemoryUsage((double) redisInfo.getUsedMemory() / redisInfo.getMaxMemory() * 100);
}

// 计算命中率
long totalHits = redisInfo.getKeyspaceHits() + redisInfo.getKeyspaceMisses();
if (totalHits > 0) {
redisInfo.setHitRate((double) redisInfo.getKeyspaceHits() / totalHits * 100);
}

// 获取复制信息
redisInfo.setReplicationRole(infoMap.get("role"));
redisInfo.setMasterHost(infoMap.get("master_host"));
redisInfo.setMasterPort(Integer.parseInt(infoMap.getOrDefault("master_port", "0")));
redisInfo.setMasterLinkStatus(Long.parseLong(infoMap.getOrDefault("master_link_status", "0")));

// 获取慢查询信息
redisInfo.setSlowLogCount(getSlowLogCount(jedis));

} catch (Exception e) {
log.error("获取Redis信息失败: {}", e.getMessage(), e);
}

return redisInfo;
}

/**
* 解析Redis信息
*/
private Map<String, String> parseRedisInfo(String info) {
Map<String, String> infoMap = new HashMap<>();

String[] lines = info.split("\r\n");
for (String line : lines) {
if (line.contains(":")) {
String[] parts = line.split(":", 2);
if (parts.length == 2) {
infoMap.put(parts[0], parts[1]);
}
}
}

return infoMap;
}

/**
* 获取慢查询数量
*/
private Long getSlowLogCount(Jedis jedis) {
try {
List<Object> slowLogs = jedis.slowlogGet(10);
return (long) slowLogs.size();
} catch (Exception e) {
return 0L;
}
}

/**
* 创建Redis监控数据
*/
private RedisMonitorData createRedisMonitorData(RedisInfo redisInfo) {
RedisMonitorData monitorData = new RedisMonitorData();

// 设置基本信息
monitorData.setHostname(getHostname());
monitorData.setIp(getLocalIpAddress());
monitorData.setPort(6379);
monitorData.setCollectTime(new Date());
monitorData.setCreateTime(new Date());

// 设置Redis信息
monitorData.setRedisVersion(redisInfo.getRedisVersion());
monitorData.setRedisMode(redisInfo.getRedisMode());
monitorData.setUsedMemory(redisInfo.getUsedMemory());
monitorData.setMaxMemory(redisInfo.getMaxMemory());
monitorData.setMemoryUsage(redisInfo.getMemoryUsage());
monitorData.setConnectedClients(redisInfo.getConnectedClients());
monitorData.setTotalCommandsProcessed(redisInfo.getTotalCommandsProcessed());
monitorData.setInstantaneousOpsPerSec(redisInfo.getInstantaneousOpsPerSec());
monitorData.setKeyspaceHits(redisInfo.getKeyspaceHits());
monitorData.setKeyspaceMisses(redisInfo.getKeyspaceMisses());
monitorData.setHitRate(redisInfo.getHitRate());
monitorData.setExpiredKeys(redisInfo.getExpiredKeys());
monitorData.setEvictedKeys(redisInfo.getEvictedKeys());
monitorData.setSlowLogCount(redisInfo.getSlowLogCount());
monitorData.setReplicationRole(redisInfo.getReplicationRole());
monitorData.setMasterHost(redisInfo.getMasterHost());
monitorData.setMasterPort(redisInfo.getMasterPort());
monitorData.setMasterLinkStatus(redisInfo.getMasterLinkStatus());

return monitorData;
}

/**
* 更新Redis缓存
*/
private void updateRedisCache(RedisMonitorData monitorData) {
try {
String cacheKey = "redis:realtime:" + monitorData.getHostname();
redisTemplate.opsForValue().set(cacheKey, monitorData, Duration.ofMinutes(5));

// 更新历史数据缓存
String historyKey = "redis:history:" + monitorData.getHostname();
redisTemplate.opsForList().leftPush(historyKey, monitorData);
redisTemplate.opsForList().trim(historyKey, 0, 99);
redisTemplate.expire(historyKey, Duration.ofHours(1));

} catch (Exception e) {
log.warn("更新Redis缓存失败: {}", e.getMessage());
}
}

/**
* 检查Redis告警
*/
private void checkRedisAlert(RedisMonitorData monitorData) {
try {
String alertType = null;
String alertLevel = null;
String alertMessage = null;

// 检查内存使用率告警
if (monitorData.getMemoryUsage() >= 95) {
alertType = "REDIS_MEMORY_CRITICAL";
alertLevel = "CRITICAL";
alertMessage = String.format("Redis内存使用率过高: %.2f%%", monitorData.getMemoryUsage());
} else if (monitorData.getMemoryUsage() >= 85) {
alertType = "REDIS_MEMORY_HIGH";
alertLevel = "WARNING";
alertMessage = String.format("Redis内存使用率较高: %.2f%%", monitorData.getMemoryUsage());
}

// 检查连接数告警
if (monitorData.getConnectedClients() > 1000) {
alertType = "REDIS_CONNECTION_HIGH";
alertLevel = "WARNING";
alertMessage = String.format("Redis连接数过多: %d", monitorData.getConnectedClients());
}

// 检查命中率告警
if (monitorData.getHitRate() < 80) {
alertType = "REDIS_HIT_RATE_LOW";
alertLevel = "WARNING";
alertMessage = String.format("Redis命中率过低: %.2f%%", monitorData.getHitRate());
}

// 检查慢查询告警
if (monitorData.getSlowLogCount() > 10) {
alertType = "REDIS_SLOW_LOG_HIGH";
alertLevel = "WARNING";
alertMessage = String.format("Redis慢查询过多: %d", monitorData.getSlowLogCount());
}

// 检查主从复制告警
if ("slave".equals(monitorData.getReplicationRole()) && monitorData.getMasterLinkStatus() == 0) {
alertType = "REDIS_REPLICATION_DOWN";
alertLevel = "CRITICAL";
alertMessage = "Redis主从复制断开";
}

// 发送告警
if (alertType != null) {
sendRedisAlert(monitorData, alertType, alertLevel, alertMessage);
}

} catch (Exception e) {
log.error("检查Redis告警失败: {}", e.getMessage(), e);
}
}

/**
* 发送Redis告警
*/
private void sendRedisAlert(RedisMonitorData monitorData, String alertType, String alertLevel, String alertMessage) {
try {
// 检查是否已经发送过相同告警
String alertKey = "redis:alert:" + monitorData.getHostname() + ":" + alertType;
Boolean hasAlert = redisTemplate.hasKey(alertKey);

if (hasAlert == null || !hasAlert) {
// 创建告警记录
RedisAlertRecord alertRecord = new RedisAlertRecord();
alertRecord.setHostname(monitorData.getHostname());
alertRecord.setIp(monitorData.getIp());
alertRecord.setPort(monitorData.getPort());
alertRecord.setAlertType(alertType);
alertRecord.setAlertLevel(alertLevel);
alertRecord.setAlertMessage(alertMessage);
alertRecord.setAlertStatus("ACTIVE");
alertRecord.setAlertTime(new Date());

// 发送告警通知
alertService.sendRedisAlert(alertRecord);

// 设置告警缓存
redisTemplate.opsForValue().set(alertKey, "1", Duration.ofMinutes(5));

log.warn("发送Redis告警: hostname={}, type={}, level={}",
monitorData.getHostname(), alertType, alertLevel);
}

} catch (Exception e) {
log.error("发送Redis告警失败: {}", e.getMessage(), e);
}
}

/**
* 获取实时Redis数据
*/
public RedisMonitorData getRealTimeRedisData(String hostname) {
String cacheKey = "redis:realtime:" + hostname;
return (RedisMonitorData) redisTemplate.opsForValue().get(cacheKey);
}

/**
* 获取Redis历史数据
*/
public List<RedisMonitorData> getRedisHistoryData(String hostname, Date startTime, Date endTime) {
return redisMonitorDataMapper.selectByHostnameAndTimeRange(hostname, startTime, endTime);
}

/**
* 获取主机名
*/
private String getHostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
return "unknown";
}
}

/**
* 获取本地IP地址
*/
private String getLocalIpAddress() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
return "127.0.0.1";
}
}
}

/**
* Redis信息实体类
*/
@Data
public class RedisInfo {
private String redisVersion; // Redis版本
private String redisMode; // Redis模式
private Long usedMemory; // 已使用内存
private Long maxMemory; // 最大内存
private Double memoryUsage; // 内存使用率
private Long connectedClients; // 连接客户端数
private Long totalCommandsProcessed; // 总处理命令数
private Long instantaneousOpsPerSec; // 每秒操作数
private Long keyspaceHits; // 键空间命中数
private Long keyspaceMisses; // 键空间未命中数
private Double hitRate; // 命中率
private Long expiredKeys; // 过期键数
private Long evictedKeys; // 驱逐键数
private Long slowLogCount; // 慢查询数量
private String replicationRole; // 复制角色
private String masterHost; // 主节点主机
private Integer masterPort; // 主节点端口
private Long masterLinkStatus; // 主链接状态
}

4. Redis优化服务

4.1 Redis优化服务

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
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/**
* Redis优化服务
* 提供Redis性能优化和调优功能
*/
@Service
public class RedisOptimizationService {

@Autowired
private RedisMonitorService redisMonitorService;

@Autowired
private AlertService alertService;

@Autowired
private JedisPool jedisPool;

/**
* 自动Redis优化
* 根据Redis性能情况自动进行优化
*/
@Scheduled(fixedRate = 300000) // 每5分钟执行一次
public void autoOptimizeRedis() {
try {
String hostname = getHostname();
RedisMonitorData redisData = redisMonitorService.getRealTimeRedisData(hostname);

if (redisData == null) {
return;
}

// 检查内存使用率
if (redisData.getMemoryUsage() > 90) {
// 内存使用率过高,执行紧急优化
executeEmergencyOptimization(redisData);
} else if (redisData.getMemoryUsage() > 80) {
// 内存使用率较高,执行预防性优化
executePreventiveOptimization(redisData);
}

// 检查命中率
if (redisData.getHitRate() < 80) {
// 命中率过低,执行缓存优化
executeCacheOptimization(redisData);
}

} catch (Exception e) {
log.error("自动Redis优化失败: {}", e.getMessage(), e);
}
}

/**
* 执行紧急优化
*/
private void executeEmergencyOptimization(RedisMonitorData redisData) {
log.warn("执行紧急Redis优化: memoryUsage={}%", redisData.getMemoryUsage());

try {
// 1. 清理过期键
cleanupExpiredKeys();

// 2. 执行内存回收
performMemoryReclaim();

// 3. 调整内存策略
adjustMemoryPolicy();

// 4. 清理大键
cleanupBigKeys();

// 5. 发送优化通知
sendOptimizationNotification(redisData, "EMERGENCY_OPTIMIZATION");

} catch (Exception e) {
log.error("执行紧急优化失败: {}", e.getMessage(), e);
}
}

/**
* 执行预防性优化
*/
private void executePreventiveOptimization(RedisMonitorData redisData) {
log.info("执行预防性Redis优化: memoryUsage={}%", redisData.getMemoryUsage());

try {
// 1. 优化内存配置
optimizeMemoryConfig();

// 2. 调整连接池配置
adjustConnectionPoolConfig();

// 3. 优化持久化配置
optimizePersistenceConfig();

// 4. 发送优化通知
sendOptimizationNotification(redisData, "PREVENTIVE_OPTIMIZATION");

} catch (Exception e) {
log.error("执行预防性优化失败: {}", e.getMessage(), e);
}
}

/**
* 执行缓存优化
*/
private void executeCacheOptimization(RedisMonitorData redisData) {
log.info("执行Redis缓存优化: hitRate={}%", redisData.getHitRate());

try {
// 1. 分析键空间
analyzeKeyspace();

// 2. 优化键过期策略
optimizeKeyExpiration();

// 3. 调整缓存策略
adjustCacheStrategy();

// 4. 发送优化通知
sendOptimizationNotification(redisData, "CACHE_OPTIMIZATION");

} catch (Exception e) {
log.error("执行缓存优化失败: {}", e.getMessage(), e);
}
}

/**
* 清理过期键
*/
private void cleanupExpiredKeys() {
log.info("清理Redis过期键");

try (Jedis jedis = jedisPool.getResource()) {
// 执行过期键清理
jedis.eval("return redis.call('del', unpack(redis.call('keys', '*')) for k,v in pairs(redis.call('keys', '*')) do if redis.call('ttl', k) == -1 then redis.call('del', k) end end");

log.info("过期键清理完成");

} catch (Exception e) {
log.error("清理过期键失败: {}", e.getMessage(), e);
}
}

/**
* 执行内存回收
*/
private void performMemoryReclaim() {
log.info("执行Redis内存回收");

try (Jedis jedis = jedisPool.getResource()) {
// 执行内存回收
jedis.memoryPurge();

log.info("内存回收完成");

} catch (Exception e) {
log.error("执行内存回收失败: {}", e.getMessage(), e);
}
}

/**
* 调整内存策略
*/
private void adjustMemoryPolicy() {
log.info("调整Redis内存策略");

try (Jedis jedis = jedisPool.getResource()) {
// 设置内存淘汰策略为allkeys-lru
jedis.configSet("maxmemory-policy", "allkeys-lru");

log.info("内存策略调整完成");

} catch (Exception e) {
log.error("调整内存策略失败: {}", e.getMessage(), e);
}
}

/**
* 清理大键
*/
private void cleanupBigKeys() {
log.info("清理Redis大键");

try (Jedis jedis = jedisPool.getResource()) {
// 查找大键
List<String> bigKeys = findBigKeys(jedis);

// 清理大键
for (String key : bigKeys) {
try {
jedis.del(key);
log.info("删除大键: {}", key);
} catch (Exception e) {
log.warn("删除大键失败: {}, error={}", key, e.getMessage());
}
}

} catch (Exception e) {
log.error("清理大键失败: {}", e.getMessage(), e);
}
}

/**
* 查找大键
*/
private List<String> findBigKeys(Jedis jedis) {
List<String> bigKeys = new ArrayList<>();

try {
// 使用SCAN命令查找大键
String cursor = "0";
do {
ScanResult<String> result = jedis.scan(cursor, new ScanParams().count(100));
cursor = result.getCursor();

for (String key : result.getResult()) {
try {
long memoryUsage = jedis.memoryUsage(key);
if (memoryUsage > 1024 * 1024) { // 大于1MB
bigKeys.add(key);
}
} catch (Exception e) {
// 忽略错误
}
}
} while (!"0".equals(cursor));

} catch (Exception e) {
log.error("查找大键失败: {}", e.getMessage(), e);
}

return bigKeys;
}

/**
* 优化内存配置
*/
private void optimizeMemoryConfig() {
log.info("优化Redis内存配置");

try (Jedis jedis = jedisPool.getResource()) {
// 设置内存使用限制
jedis.configSet("maxmemory", "2gb");

// 设置内存淘汰策略
jedis.configSet("maxmemory-policy", "allkeys-lru");

// 设置内存回收阈值
jedis.configSet("active-defrag-threshold-lower", "10");
jedis.configSet("active-defrag-threshold-upper", "100");

log.info("内存配置优化完成");

} catch (Exception e) {
log.error("优化内存配置失败: {}", e.getMessage(), e);
}
}

/**
* 调整连接池配置
*/
private void adjustConnectionPoolConfig() {
log.info("调整Redis连接池配置");

try (Jedis jedis = jedisPool.getResource()) {
// 设置最大连接数
jedis.configSet("maxclients", "10000");

// 设置连接超时
jedis.configSet("timeout", "300");

log.info("连接池配置调整完成");

} catch (Exception e) {
log.error("调整连接池配置失败: {}", e.getMessage(), e);
}
}

/**
* 优化持久化配置
*/
private void optimizePersistenceConfig() {
log.info("优化Redis持久化配置");

try (Jedis jedis = jedisPool.getResource()) {
// 设置RDB保存策略
jedis.configSet("save", "900 1 300 10 60 10000");

// 设置AOF策略
jedis.configSet("appendonly", "yes");
jedis.configSet("appendfsync", "everysec");

log.info("持久化配置优化完成");

} catch (Exception e) {
log.error("优化持久化配置失败: {}", e.getMessage(), e);
}
}

/**
* 分析键空间
*/
private void analyzeKeyspace() {
log.info("分析Redis键空间");

try (Jedis jedis = jedisPool.getResource()) {
// 获取键空间信息
String info = jedis.info("keyspace");
log.info("键空间信息: {}", info);

// 分析键的分布
analyzeKeyDistribution(jedis);

} catch (Exception e) {
log.error("分析键空间失败: {}", e.getMessage(), e);
}
}

/**
* 分析键的分布
*/
private void analyzeKeyDistribution(Jedis jedis) {
try {
Map<String, Integer> keyTypes = new HashMap<>();
String cursor = "0";

do {
ScanResult<String> result = jedis.scan(cursor, new ScanParams().count(100));
cursor = result.getCursor();

for (String key : result.getResult()) {
try {
String type = jedis.type(key);
keyTypes.put(type, keyTypes.getOrDefault(type, 0) + 1);
} catch (Exception e) {
// 忽略错误
}
}
} while (!"0".equals(cursor));

log.info("键类型分布: {}", keyTypes);

} catch (Exception e) {
log.error("分析键分布失败: {}", e.getMessage(), e);
}
}

/**
* 优化键过期策略
*/
private void optimizeKeyExpiration() {
log.info("优化Redis键过期策略");

try (Jedis jedis = jedisPool.getResource()) {
// 设置过期键清理策略
jedis.configSet("hz", "10");

log.info("键过期策略优化完成");

} catch (Exception e) {
log.error("优化键过期策略失败: {}", e.getMessage(), e);
}
}

/**
* 调整缓存策略
*/
private void adjustCacheStrategy() {
log.info("调整Redis缓存策略");

try (Jedis jedis = jedisPool.getResource()) {
// 设置缓存策略
jedis.configSet("maxmemory-policy", "allkeys-lru");

log.info("缓存策略调整完成");

} catch (Exception e) {
log.error("调整缓存策略失败: {}", e.getMessage(), e);
}
}

/**
* 发送优化通知
*/
private void sendOptimizationNotification(RedisMonitorData redisData, String optimizationType) {
try {
AlertMessage alert = new AlertMessage();
alert.setType("REDIS_OPTIMIZATION");
alert.setLevel("INFO");
alert.setMessage(String.format("Redis优化完成: 类型=%s, 内存使用率=%.2f%%, 命中率=%.2f%%",
optimizationType, redisData.getMemoryUsage(), redisData.getHitRate()));
alert.setTimestamp(new Date());

alertService.sendAlert(alert);

} catch (Exception e) {
log.error("发送优化通知失败: {}", e.getMessage(), e);
}
}

/**
* 获取主机名
*/
private String getHostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
return "unknown";
}
}
}

5. 总结

本文详细介绍了Redis运维监控与优化的完整解决方案,包括:

5.1 核心技术点

  1. Redis监控: 实时监控Redis性能指标、内存使用、连接数等
  2. 性能分析: 分析Redis命中率、慢查询、内存使用趋势
  3. 自动优化: 自动内存回收、键清理、配置优化
  4. 故障诊断: 快速定位Redis性能问题和故障
  5. 告警通知: 多级告警、智能通知

5.2 架构优势

  1. 实时监控: 5秒间隔的实时Redis数据采集
  2. 智能告警: 基于阈值的智能告警机制
  3. 自动优化: 自动化的Redis性能优化
  4. 多维度分析: 内存、命中率、连接数等多维度分析

5.3 最佳实践

  1. 监控策略: 设置合理的Redis监控阈值
  2. 优化策略: 根据性能情况执行针对性优化
  3. 内存管理: 合理设置内存策略和淘汰机制
  4. 预防措施: 提前预防Redis性能问题

通过以上架构设计,可以构建完善的Redis运维监控系统,实现Redis服务的有效管理和性能优化。