**接口契约重点**:Queue 层不直接调用 Worker,Scheduler 层不接触数据库。所有跨层调用必须通过显式接口,禁止私自绕过。
---
### 3.4 数据流与控制流
**控制流方向**(单向信任链):
API → Queue (校验通过后) → Scheduler (可调度时) → Worker (实际执行)
**数据流方向**(双向但有限权):
- 写入:Queue 接收到任务后,先写入 Persistence 再返回成功(写后日志)。
- 读取:Scheduler 从 Queue 拉取任务时,Queue 先读取 Persistence 中的数据到内存缓存,再返回给 Scheduler。
**信任链路**:每层只信任上一层发出的接口数据。例如 Scheduler 不信任 Worker 自行上报的完成时间,必须由 Queue 层根据状态机回写最终状态。
---
### 3.5 选型权衡
| 决策点 | 方案A | 方案B | 推荐及理由 |
|--------|-------|-------|-----------|
| Queue 内核 | 纯内存 (Redis List) | 自建优先级堆 (RBTree) | 推荐方案B:规则灵活、去重可控,Redis 适合简单 FIFO 但难以处理优先级变更 |
| 持久化策略 | 每次操作全量刷盘 | 批量异步刷盘 + WAL | 推荐异步批量:性能与可靠性的折中,延迟控制在 10ms 内 |
| 调度策略 | 简单轮询 | 加权公平队列 (WFQ) | 推荐 WFQ:避免低优先级任务被饿死,且可支持权重自定义 |
---
### 3.6 风险点
1. **队列堆积阻塞**:当 Worker 处理速度低于入队速度时,内存中 Ready 队列可能占满。
- 缓解:设置入队限流,队列长度超阈值时返回 429;启用背压机制通知 API 层减速。
2. **持久化写入延迟导致丢失**:异步刷盘在崩溃时可能丢失最近一批任务。
- 缓解:关键任务(高优先级)可配置同步写入,牺牲部分性能。
3. **层间依赖环**:若 Scheduler 依赖 Queue,Queue 又依赖 Scheduler 的状态回查,则形成环形依赖。
- 缓解:严格约定状态回查只能由 Scheduler → Queue → Persistence,禁止反向调用。
4. **死锁**:多个 Scheduler 同时 Dequeue 时若锁粒度不当,可能死锁。
- 缓解:使用乐观锁 + 重试机制,避免长事务。
---
### 3.7 落地步骤
| 阶段 | 任务 | 输出 |
|------|------|------|
| 1 | 定义每层接口规范(Proto 或 JSON Schema) | 接口文档 + mock 测试桩 |
| 2 | 实现 Persistence 层:选型数据库 + 表结构 | 可独立运行的存储模块 |
| 3 | 实现 Queue 层:内存优先级堆 + 延迟桶 + 持久化桥接 | 单机可通过单元测试的队列核心 |
| 4 | 实现 Scheduler 层:Worker 管理 + 限流 + 重试 | 可调度 3 个 Worker 的调度器 |
| 5 | 集成 API 层:提供 HTTP/gRPC 入口 | 返回有效 Ticket 的全链路闭环 |
| 6 | 压测 + 故障注入(模拟崩溃、网络分区) | 恢复 RTO ≤ 30s,RPO ≤ 1 条任务 |
---
### 3.8 验收标准
> **通过条件**:所有验收项必须在分布式部署下(至少 2 节点)通过。
1. **分层隔离测试**:替换 Persistence 层为内存模拟实现后,Queue 功能应正常运行,无需修改上层代码。
2. **接口契约测试**:每层接口的输入输出严格符合定义,非法输入返回明确定义的错误码。
3. **状态机正确性**:任务状态流转(Pending→Ready→Delayed→Running→Done/Failed)不出现非法跳转。
4. **崩溃恢复**:随机 Kill 一个节点后,已提交的任务在 30 秒内被重新调度,不丢失任务(RPO=0)。
5. **优先级保序**:高优先级任务(priority=1)始终比低优先级(priority=10)先被调度,延迟不超过 100ms。