完整架构
生产级架构
生产级延时队列不是某一种技术方案的放大版,而是多种方案的组合。短延时任务要求低延迟,可以放在 Redis ZSET 或时间轮里;中长延时任务更看重持久化和可恢复,可以放在数据库里;超大规模任务需要分片调度、消费者集群和补偿扫描共同工作。
整体架构图
┌─────────────────────────────────────────────────────────────────┐
│ 延时队列系统架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 客户端层(Client) │ │
│ │ ├─ Web 应用 │ │
│ │ ├─ 移动应用 │ │
│ │ └─ 定时任务 │ │
│ └──────────────────┬──────────────────────────────────────┘ │
│ │ REST API / gRPC │
│ ┌──────────────────▼──────────────────────────────────────┐ │
│ │ 网关层(Gateway) │ │
│ │ ├─ 负载均衡 │ │
│ │ ├─ 限流熔断 │ │
│ │ └─ 认证授权 │ │
│ └──────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────▼──────────────────────────────────────┐ │
│ │ 业务层(Business) │ │
│ │ ├─ 任务管理服务 │ │
│ │ ├─ 任务路由服务 │ │
│ │ ├─ 任务编排服务 │ │
│ │ └─ 任务监控服务 │ │
│ └──────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────▼──────────────────────────────────────┐ │
│ │ 服务层(Service) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ 调度器集群 │ │ 消费者集群 │ │ 监控集群 │ │ │
│ │ │ Scheduler │ │ Consumer │ │ Monitor │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ ├─ Scheduler│ │ ├─ Worker-1 │ │ ├─ Prometheus│ │ │
│ │ │ ├─ Scheduler│ │ ├─ Worker-2 │ │ ├─ Grafana │ │ │
│ │ │ └─ Scheduler│ │ ├─ Worker-3 │ │ └─ AlertMgr │ │ │
│ │ │ ... │ │ ... │ │ │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └──────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────▼──────────────────────────────────────┐ │
│ │ 存储层(Storage) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Redis 集群 │ │ MySQL 集群 │ │ Kafka 集群 │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ ├─ Master-1 │ │ ├─ Master-1 │ │ ├─ Broker-1 │ │ │
│ │ │ ├─ Master-2 │ │ ├─ Master-2 │ │ ├─ Broker-2 │ │ │
│ │ │ └─ Master-3 │ │ └─ Slave-1 │ │ └─ Broker-3 │ │ │
│ │ │ │ │ ... │ │ ... │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ 分层存储策略 │ │ │
│ │ │ │ │ │
│ │ │ 热数据层(Redis) │ │ │
│ │ │ ├─ 延时 < 30 分钟 │ │ │
│ │ │ ├─ 精度:秒级 │ │ │
│ │ │ └─ 内存:~50MB(峰值) │ │ │
│ │ │ │ │ │
│ │ │ 温数据层(MySQL) │ │ │
│ │ │ ├─ 延时 30 分钟 ~ 7 天 │ │ │
│ │ │ ├─ 精度:分钟级 │ │ │
│ │ │ └─ 存储:~1GB │ │ │
│ │ │ │ │ │
│ │ │ 冷数据层(MySQL 长表) │ │ │
│ │ │ ├─ 延时 > 7 天 │ │ │
│ │ │ ├─ 精度:小时级 │ │ │
│ │ │ └─ 存储:~500MB │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘核心组件
1. 任务管理服务
任务管理服务负责接收业务方提交的延时任务,校验参数,生成任务 ID,并记录任务状态。它不直接执行任务,也不承担长时间等待;它只保证任务被正确写入系统。
这一层最重要的是状态模型。一个任务至少要能表达等待中、处理中、已完成、失败、取消和死信。状态清楚,后面的调度、重试、补偿才有依据。
2. 调度器集群
调度器集群负责发现到期任务,并把它们推进到可消费状态。它要解决三个问题:扫描哪些任务、一次取多少、如何避免多个调度器重复领取。
短延时任务可以高频扫描,长延时任务可以降低扫描频率。调度器不应该把所有任务都按同一个节奏处理,否则不是浪费资源,就是延迟不可控。
3. 消费者集群
消费者集群负责真正执行业务动作,例如取消订单、关闭优惠券、发送提醒或触发补偿任务。消费者要能幂等处理,因为调度层只能尽量减少重复,不能保证重复永远不会发生。
消费者还要把失败原因写回系统。失败不是一个简单的布尔值,至少要区分临时失败、业务失败和不可恢复失败。只有这样,系统才能决定是重试、延后、进入死信,还是直接结束。
高可用设计
主备切换
高可用设计的核心是让任务不绑定机器。调度器挂了,任务范围可以迁移;消费者挂了,处理中超时任务可以重新投递;存储节点异常,系统可以降级到更保守的扫描策略。
主备切换要有明确的租约和版本。新节点接管时必须证明旧节点已经失去资格,旧节点恢复后也必须先检查自己是否仍然拥有任务范围。
监控告警
监控指标
延时队列的监控不能只看 QPS。更关键的是延迟偏差、任务积压、失败重试、死信数量、调度器心跳和消费耗时。
一套实用的告警规则应该回答四个问题:
- 任务有没有按时进入可消费状态?
- 到期任务有没有越积越多?
- 某类任务是否持续失败?
- 调度器或消费者是否出现大面积失联?
小结
完整架构的价值,是把等待、调度、执行、失败和恢复放到同一个状态闭环里。读者不需要记住每种中间件的所有细节,但要能判断:这个任务现在在哪里,为什么还没执行,失败后谁会接手,重复执行会不会伤害业务。