You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.6 KiB
4.6 KiB
Redis 日志管理功能优化
问题描述
原始代码的日志管理逻辑存在问题:
- 只处理包含
%的日志行,导致其他重要日志被忽略 - 对于进度日志的处理逻辑不清晰
- 没有正确实现"记录所有日志,但进度日志只保留最新"的需求
新的实现逻辑
核心需求
- 记录所有日志:不只是包含
%的日志,所有训练日志都应该记录 - 进度日志去重:当遇到包含
%的进度日志时,删除之前的进度日志,只保留最新的 - 容量控制:最多保存 50 条日志,超过时删除最旧的
- 过期时间:所有日志保存 5 天
修改后的方法
manageTrainingLogInRedis
private void manageTrainingLogInRedis(Integer trainId, String logLine) {
try {
if (logLine == null || logLine.trim().isEmpty()) {
return;
}
String redisKey = "yolo:training_log:" + trainId;
boolean isProgressLog = logLine.contains("%");
if (isProgressLog) {
// 如果是进度日志(包含%),先删除之前的进度日志
removeProgressLogs(redisKey);
}
// 添加新的日志行到列表末尾
redisUtil.lSet(redisKey, logLine, 5 * 24 * 60 * 60); // 5天过期时间(秒)
// 检查列表长度,如果超过50条,删除第一条
long newSize = redisUtil.lGetListSize(redisKey);
if (newSize > 50) {
redisUtil.lRemove(redisKey, 1, redisUtil.lGetIndex(redisKey, 0));
}
log.debug("训练日志已存储到Redis - 训练ID: {}, 日志类型: {}, 当前日志数量: {}",
trainId, isProgressLog ? "进度日志" : "普通日志", redisUtil.lGetListSize(redisKey));
} catch (Exception e) {
log.error("管理训练日志Redis操作失败 - 训练ID: {}", trainId, e);
}
}
removeProgressLogs
新增的辅助方法,专门用于删除所有进度日志:
private void removeProgressLogs(String redisKey) {
try {
// 获取所有日志
java.util.List<Object> allLogs = redisUtil.lGet(redisKey, 0, -1);
// 找出并删除所有包含%的日志
for (int i = allLogs.size() - 1; i >= 0; i--) {
Object logObj = allLogs.get(i);
if (logObj != null) {
String logStr = logObj.toString();
if (logStr.contains("%")) {
redisUtil.lRemove(redisKey, 1, logStr);
log.debug("删除旧的进度日志: {}", logStr);
}
}
}
} catch (Exception e) {
log.error("删除进度日志时出错 - Redis键: {}", redisKey, e);
}
}
工作流程示例
场景1:普通日志
输入: "YOLO训练开始"
处理: 直接添加到Redis列表
结果: Redis列表: ["YOLO训练开始"]
场景2:进度日志(第一次)
输入: "Epoch 1/100: 50%|█████ | 100/200 [00:30<00:30]"
处理: 添加到Redis列表
结果: Redis列表: ["YOLO训练开始", "Epoch 1/100: 50%|█████ | 100/200 [00:30<00:30]"]
场景3:进度日志(更新)
输入: "Epoch 1/100: 75%|███████▌ | 150/200 [00:45<00:15]"
处理: 1. 删除之前的进度日志 2. 添加新的进度日志
结果: Redis列表: ["YOLO训练开始", "Epoch 1/100: 75%|███████▌ | 150/200 [00:45<00:15]"]
场景4:混合日志
输入序列:
1. "模型加载完成" -> 普通日志,直接添加
2. "Epoch 1/100: 25%|██▌ | 50/200 [00:15<00:45]" -> 进度日志,添加
3. "数据预处理完成" -> 普通日志,直接添加
4. "Epoch 1/100: 50%|█████ | 100/200 [00:30<00:30]" -> 进度日志,删除之前的进度日志并添加
最终Redis列表:
["模型加载完成", "数据预处理完成", "Epoch 1/100: 50%|█████ | 100/200 [00:30<00:30]"]
优势
- 完整性:所有重要日志都被保存,不会遗漏
- 效率性:进度日志只保留最新状态,避免重复
- 可控性:最多50条日志,防止Redis占用过多内存
- 可维护性:清晰的日志类型区分和调试信息
日志类型
- 普通日志:训练开始、模型加载、错误信息等
- 进度日志:包含
%的进度条信息,如训练进度
Redis 键格式
yolo:training_log:{trainId}
例如:
yolo:training_log:12345
过期时间
所有日志条目设置 5 天过期时间(432,000 秒),自动清理旧数据。