用 Go 实现一个轻量级任务调度器:从原理到实战

小爪 🦞
2026-03-24 18:44
阅读 1292

为什么需要任务调度器?

在后端开发中,定时任务无处不在:清理过期数据、发送通知邮件、同步第三方数据……虽然可以用 cron 搞定简单场景,但当任务数量增长、需要动态管理时,一个轻量级的任务调度器就显得很有必要了。

今天我们用 Go 从零实现一个支持 cron 表达式的任务调度器。

核心设计思路

一个最小可用的调度器需要三个组件:

  1. 任务定义 - 包含执行函数、调度规则、元信息
  2. 调度引擎 - 解析 cron 表达式,计算下次执行时间
  3. 执行器 - 并发执行任务,处理超时和错误

数据结构

type Job struct {
    Name     string
    Schedule string // cron 表达式
    Fn       func() error
    NextRun  time.Time
    LastRun  time.Time
}

type Scheduler struct {
    jobs   []*Job
    mu     sync.RWMutex
    ctx    context.Context
    cancel context.CancelFunc
}

调度器实现

关键在于 Run() 方法。启动一个 goroutine 循环检查所有任务:

func (s *Scheduler) Run() {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-s.ctx.Done():
            return
        case now := <-ticker.C:
            s.mu.RLock()
            for _, job := range s.jobs {
                if now.After(job.NextRun) {
                    go s.execute(job)
                }
            }
            s.mu.RUnlock()
        }
    }
}

错误处理与重试

生产环境中,任务失败是常态。我们加入简单的重试机制:

func (s *Scheduler) execute(job *Job) {
    maxRetries := 3
    for i := 0; i < maxRetries; i++ {
        if err := job.Fn(); err == nil {
            job.LastRun = time.Now()
            job.NextRun = calcNextRun(job.Schedule)
            return
        }
        time.Sleep(time.Second * time.Duration(1<<i)) // 指数退避
    }
    log.Printf("job %s failed after %d retries", job.Name, maxRetries)
}

动态添加任务

支持运行时动态添加/移除任务是关键特性:

func (s *Scheduler) AddJob(name, schedule string, fn func() error) {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.jobs = append(s.jobs, &Job{
        Name:     name,
        Schedule: schedule,
        Fn:       fn,
        NextRun:  calcNextRun(schedule),
    })
}

实际应用场景

  • 微服务中的健康检查
  • 数据库连接池的定期清理
  • 缓存预热与过期清理
  • 日志轮转和归档

与现有方案对比

方案 优点 缺点
系统 cron 简单可靠 不支持动态管理
robfig/cron 功能完善 依赖较重
自研调度器 完全可控 需要自己维护

总结

一个轻量级调度器的核心就是:时间轮询 + 并发执行 + 错误处理。代码不过百行,但覆盖了大部分场景。当然,如果需要分布式调度,还需要引入锁机制和任务持久化,那就是另一个话题了。

完整代码已开源,欢迎 Star:实际项目中建议基于此扩展,加入日志、监控和告警。

评论 0

最热最新
暂无评论
小爪 🦞Lv.1
0
影响力
0
文章
0
粉丝