高 进阶
延迟任务方案对比#
一句话答案#
四种方案按推荐度:延迟 MQ(可靠简单)> Redis ZSET > 时间轮(进程内)> DB 轮询(兜底)。
核心要点
| 方案 | 精度 | 可靠性 | 适用 |
|---|---|---|---|
| 延迟MQ | 秒~分 | 高 | 通用(推荐) |
| Redis ZSET | 秒级 | 中 | 量不大 |
| 时间轮 | ms级 | 低 | 进程内 |
| DB轮询 | 分钟 | 高 | 兜底方案 |
面试回答(2分钟版)
延迟任务有四种主流方案,按推荐程度排序。首选是延迟消息队列,比如RocketMQ原生支持延迟消息,可靠性高、使用简单,精度在秒到分钟级,适合大多数业务场景比如订单超时取消。第二是Redis ZSet方案,把任务ID作为member、触发时间戳作为score存入ZSet,后台线程定时用ZRANGEBYSCORE取出到期任务执行,精度秒级,适合数据量不大的场景。第三是时间轮,比如Netty的HashedWheelTimer,精度可以到毫秒级,性能极高,但它是单机内存方案,进程挂了任务就丢了,适合进程内的超时管理比如连接超时检测。第四是数据库轮询,定时扫描DB中状态为待执行且到期的记录,精度分钟级,大表扫描开销大,但胜在可靠简单,适合作为兜底方案。实际项目中通常以延迟MQ为主,DB轮询做兜底补偿。
追问与易错
追问方向:
- “Redis ZSET 延迟任务怎么实现?”→ 将任务 ID 作为 member、触发时间戳作为 score 存入 ZSet,后台线程定时用 ZRANGEBYSCORE 取出到期任务(score <= now)执行,执行后 ZREM 删除;注意多消费者时用 Lua 保证取出和删除的原子性
- “时间轮优缺点?”→ 优点是 O(1) 插入和触发、精度可达毫秒级、内存紧凑;缺点是单机内存方案进程挂了任务全丢、大量空槽浪费遍历时间(层级时间轮可优化)
- “为什么推荐 MQ?”→ RocketMQ/RabbitMQ 的延迟消息有持久化和重试保障不会丢消息,使用简单只需发消息时设延迟级别,天然支持分布式多消费者,可靠性远高于 Redis 和时间轮方案
易错点:
- ❌ 定时扫描 DB 性能好——大表扫描开销大
- ❌ 时间轮适合所有场景——单机内存方案