Files
ycc-proxy-server/解冻任务实现方案说明.md

133 lines
4.6 KiB
Markdown
Raw Normal View History

2025-12-02 19:57:10 +08:00
# 解冻任务实现方案说明
## 方案对比
### 方案1Asynq 延迟任务(已实现但未使用)
**优点:**
- ✅ 精确到秒级执行
- ✅ 自动重试机制
- ✅ 无需额外调度器
**缺点:**
- ❌ 依赖 Redis 持久化Redis 数据丢失会导致任务丢失
- ❌ 系统长时间停机可能导致延迟任务过期
- ❌ 需要补偿机制
### 方案2定时任务扫描✅ 已采用)
**优点:**
-**数据持久化在数据库,更可靠**(核心优势)
-**系统停机后重启,定时任务会继续扫描并处理**(核心优势)
- ✅ 可以批量处理,效率高
- ✅ 已有定时任务基础设施
- ✅ 不依赖 Redis 持久化
**缺点:**
- ⚠️ 执行时间不够精确取决于扫描频率如每5分钟扫描一次
- ⚠️ 需要处理并发扫描(已通过乐观锁解决)
## 最终选择:定时任务扫描方案
### 选择理由
1. **金融场景,可靠性优先**:涉及资金解冻,必须保证任务不丢失
2. **解冻时间允许延迟**:解冻时间可以有一定的延迟(比如几分钟内都可以接受)
3. **已有基础设施**:项目中已有定时任务实现(`cleanQueryData.go`
4. **数据库表已设计好**`status``unfreeze_time` 字段支持扫描查询
## 实现细节
### 1. 定时任务配置
- **执行频率**每2小时执行一次`0 */2 * * *`- 节省性能
- **任务类型**`MsgUnfreezeCommissionScan`
- **处理器**`UnfreezeCommissionScanHandler`
- **批次大小**每次最多处理2个任务避免并发太多
### 2. 扫描逻辑
```go
// 查询条件:
// - status = 1待解冻
// - unfreeze_time <= 当前时间
// - del_state = 0未删除
// - 按 unfreeze_time 升序排序
```
### 3. 并发安全
- 使用**乐观锁**`version` 字段)确保并发安全
- 每个任务在事务中处理,确保原子性
- 双重检查:查询后再次检查状态,防止并发处理
### 4. 错误处理
- 单个任务失败不影响其他任务
- 记录详细的错误日志
- 失败的任务会在下次扫描时重试
### 5. 性能优化
- 使用数据库索引优化查询(`idx_status``idx_unfreeze_time`
- **扫描频率**每2小时扫描一次减少数据库查询压力
- **查询所有任务**:每次扫描找到所有需要解冻的任务(不限制数量)
- **并发控制**使用信号量Semaphore限制最多同时处理2个任务
- **批量处理**:所有任务都会处理,但通过并发控制避免同时处理太多,节省性能
## 代码文件
### 新增文件
- `app/main/api/internal/queue/unfreezeCommissionScan.go` - 定时扫描处理器
### 修改文件
- `app/main/api/internal/queue/routes.go` - 注册定时任务
- `app/main/api/internal/queue/agentProcess.go` - 移除发送延迟任务的逻辑
- `app/main/api/internal/types/taskname.go` - 添加任务类型常量
### 保留文件(备用)
- `app/main/api/internal/queue/unfreezeCommission.go` - 延迟任务处理器(保留作为备用)
- `app/main/api/internal/service/asynqService.go` - `SendUnfreezeTask` 方法(保留作为备用)
## 执行流程
```
定时任务启动每2小时
扫描数据库status=1 AND unfreeze_time <= 当前时间
查询所有需要解冻的任务(不限制数量)
并发处理使用信号量限制最多同时2个
├─ 任务1goroutine 1
├─ 任务2goroutine 2
├─ 任务3等待直到前2个完成
├─ 任务4等待直到前2个完成
└─ ...(以此类推,两个两个处理)
每个任务使用事务 + 乐观锁处理
更新任务状态status = 2已解冻
更新钱包FrozenBalance -= 冻结金额, Balance += 冻结金额
等待所有任务完成
记录日志
```
## 监控建议
1. **监控扫描任务执行情况**
- 检查定时任务是否正常执行
- 监控每次扫描找到的任务数量
- 监控成功/失败数量
2. **监控解冻延迟**
- 记录 `actual_unfreeze_time - unfreeze_time` 的差值
- 如果延迟超过10分钟需要检查定时任务是否正常
3. **监控异常情况**
- 冻结余额不足的情况(数据异常)
- 任务状态异常的情况
## 后续优化建议
1. **可配置扫描频率**将扫描频率当前5分钟配置到配置表
2. **批次大小限制**:如果任务量很大,可以限制每次处理的数量
3. **告警机制**:如果连续多次扫描都失败,发送告警
4. **补偿机制**:提供手动触发扫描的接口,用于紧急情况