Files
ycc-proxy-server/解冻任务优化建议.md
2025-12-02 19:57:10 +08:00

5.0 KiB
Raw Blame History

解冻任务优化建议

当前实现分析

优点

使用信号量控制并发,避免数据库压力过大
使用事务和乐观锁保证数据一致性
双重检查防止重复处理
错误处理不中断整体流程

可改进点

1. ⚠️ 超时控制(重要)

问题:如果某个任务处理时间过长(比如数据库慢查询),会阻塞整个扫描流程。

建议:为每个任务添加超时控制

// 为每个任务设置30秒超时
taskCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()

err := l.svcCtx.AgentFreezeTaskModel.Trans(taskCtx, func(transCtx context.Context, session sqlx.Session) error {
    // ... 处理逻辑
})

2. 📊 批次大小限制(可选)

问题:如果任务量非常大(比如几千个),一次性查询所有会占用大量内存。

建议:如果任务量超过一定数量,可以分批处理

const maxBatchSize = 1000 // 每次最多查询1000个
if len(freezeTasks) > maxBatchSize {
    logx.Warnf("任务数量过多(%d),本次只处理前%d个剩余将在下次扫描处理", len(freezeTasks), maxBatchSize)
    freezeTasks = freezeTasks[:maxBatchSize]
}

3. 🔄 错误分类处理

问题:所有错误都统一处理,没有区分临时错误和永久错误。

建议:区分错误类型,临时错误可以重试,永久错误跳过

if err != nil {
    // 判断错误类型
    if isTemporaryError(err) {
        // 临时错误,记录但继续处理其他任务
        logx.Errorf("解冻任务临时失败,将在下次扫描重试: freezeTaskId=%d, err=%v", task.Id, err)
    } else {
        // 永久错误(如数据异常),记录详细日志
        logx.Errorf("解冻任务永久失败: freezeTaskId=%d, err=%v", task.Id, err)
    }
}

4. ⏱️ 处理时间监控

问题:缺少处理时间统计,无法评估性能。

建议:记录处理时间,便于监控和优化

startTime := time.Now()
// ... 处理逻辑
duration := time.Since(startTime)
logx.Infof("解冻任务处理耗时: freezeTaskId=%d, duration=%v", task.Id, duration)

5. 🛡️ 优雅关闭支持

问题:如果服务关闭,正在处理的任务可能被中断。

建议:检查 context 是否被取消

select {
case <-ctx.Done():
    logx.Infof("扫描任务被取消,已处理: 成功=%d, 失败=%d", successCount, failCount)
    return ctx.Err()
default:
    // 继续处理
}

6. 📈 延迟统计

问题:无法知道任务延迟了多久才被处理。

建议:记录延迟时间,便于监控

delay := time.Since(currentTask.UnfreezeTime)
if delay > 1*time.Hour {
    logx.Warnf("解冻任务延迟处理: freezeTaskId=%d, 延迟=%v", task.Id, delay)
}

7. 🔍 数据库连接池监控

问题:并发处理时可能耗尽数据库连接池。

建议:监控连接池使用情况,如果连接数不足,降低并发数

// 可以根据数据库连接池情况动态调整并发数
maxConcurrency := 2
if dbConnPoolAvailable < 5 {
    maxConcurrency = 1 // 连接池紧张时降低并发
}

8. 🎯 幂等性增强

问题:虽然有乐观锁,但可以进一步优化。

建议:添加更多的幂等性检查

// 检查是否已经解冻过(通过 actual_unfreeze_time
if currentTask.ActualUnfreezeTime.Valid {
    logx.Infof("任务已解冻,跳过: freezeTaskId=%d", task.Id)
    return nil
}

9. 📝 更详细的日志

问题:日志信息可以更详细,便于排查问题。

建议:添加更多上下文信息

logx.Infof("解冻任务详情: freezeTaskId=%d, agentId=%d, amount=%.2f, orderPrice=%.2f, freezeTime=%v, unfreezeTime=%v, delay=%v",
    task.Id, currentTask.AgentId, currentTask.FreezeAmount, currentTask.OrderPrice,
    currentTask.FreezeTime, currentTask.UnfreezeTime, delay)

10. 🔧 配置化并发数

问题并发数硬编码为2不够灵活。

建议:从配置表读取并发数

// 从配置表读取并发数默认2
maxConcurrency, err := l.svcCtx.AgentConfigModel.FindOneByConfigKey(ctx, "unfreeze_max_concurrency")
if err != nil || maxConcurrency == nil {
    maxConcurrency = 2 // 默认值
}

优先级建议

🔴 高优先级(建议立即实现)

  1. 超时控制 - 防止任务卡死
  2. 错误分类处理 - 提高可靠性

🟡 中优先级(建议后续优化)

  1. 处理时间监控 - 便于性能优化
  2. 延迟统计 - 便于监控
  3. 更详细的日志 - 便于排查问题

🟢 低优先级(可选)

  1. 批次大小限制 - 如果任务量不大可以不做
  2. 优雅关闭 - 如果服务很少重启可以不做
  3. 配置化并发数 - 如果并发数不需要调整可以不做

实施建议

建议先实现超时控制错误分类处理,这两个对可靠性影响最大。其他优化可以根据实际运行情况逐步添加。