513 words
3 minutes
如何设计高可用的分布式定时任务系统

定时任务是后端开发中的常见需求,如何设计高可用的分布式任务系统?

单机定时任务的问题#

// ❌ 单机定时任务
setInterval(async () => {
await processOrders();
}, 60000);
// 问题:
// 1. 单点故障 - 机器宕机任务停止
// 2. 重复执行 - 集群部署会执行多次
// 3. 无法动态管理

解决方案#

1. 任务分片#

-- 按 ID 取模分片
SELECT * FROM orders
WHERE id % 10 = SHARD_ID
AND status = 'pending';

2. 分布式锁#

// 使用 Redis 实现分布式锁
async function acquireLock(key, ttl = 30) {
const result = await redis.setnx(`lock:${key}`, Date.now());
return result === 1;
}
async function releaseLock(key) {
await redis.del(`lock:${key}`);
}

3. 延迟队列#

interface DelayJob {
id: string;
topic: string;
payload: any;
delayTime: number;
attempt: number;
}
// 使用 Redis ZSet 实现延迟队列
class DelayQueue {
async push(job: DelayJob) {
const score = Date.now() + job.delayTime;
await redis.zadd('delay:queue', score, JSON.stringify(job));
}
async pop(timeout = 5): Promise<DelayJob | null> {
const result = await redis.bzpopmin('delay:queue', timeout);
return result ? JSON.parse(result[1]) : null;
}
}
TIP

推荐使用开源方案:XXL-JOB、ElasticJob、ScheduleJS

整体架构#

┌─────────────────────────────────────────┐
│ API │
└─────────────────┬───────────────────────┘
┌─────────────────▼───────────────────────┐
│ 任务调度中心 │
│ (分配任务、检查心跳、故障转移) │
└─────────────────┬───────────────────────┘
┌─────────────────▼───────────────────────┐
│ 执行器集群 (Worker) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Worker 1 │ │Worker 2 │ │Worker 3 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────┬───────────────────────┘
┌─────────────────▼───────────────────────┐
│ Redis / MySQL │
└─────────────────────────────────────────┘

核心特性#

特性说明
高可用多 Worker 集群,故障自动转移
幂等性任务执行结果可追溯,支持重试
动态管理支持任务启停、修改参数
监控告警执行时间、成功率、异常报警
日志追踪任务执行日志完整记录

关键代码#

@JobExecutor("orderProcessJob")
public void execute(JobArgs args) {
log.info("开始处理订单: {}", args.getJobId());
// 1. 检查任务是否已执行
if (!jobService.checkAndLock(args.getJobId())) {
log.warn("任务已被其他节点执行");
return;
}
// 2. 执行业务逻辑
orderService.process(args.getOrderId());
// 3. 更新任务状态
jobService.complete(args.getJobId());
}

总结#

设计分布式任务系统需要考虑:

  1. 可靠性 - 任务不丢失、不重复
  2. 可用性 - 故障自动转移
  3. 可观测性 - 完整日志和监控
  4. 性能 - 支持大量任务并发执行