如何设计一个定时任务?

developS / 2023-08-19 / 原文

一.日常工作中使用到的框架?

单机:Quartz,Spring Schedule 等框架;

分布式: SchedulerX,ElasticJob,xxlJob 等分布式任务调度

二.定时任务的作用

简单来讲为某个时间执行某些具体的任务

1.数据获取  2.财务账目核对 3.定时数据备份 4.定时更新数据平台的数据

三.定时任务可以使用什么数据结构来实现?

3.1 数组

将所有的任务存放在一个数组里面,间隔单位时间遍历数组,找到满足时间的任务,查询时间复杂度为o(N),

新增任务即为新增一个元素。

3.2 优先队列

随着时间的增加,超过时间的任务已经被执行过或者丢弃了,因此我们只需要查询最接近当前时间的,即前几个最小的任务,可以使用小根堆实现。

新增任务即为往树里面插入元素,时间复杂度为o(log(N)),查找复杂度为o(log(N))

3.3时间轮算法

  多层次时间轮,就跟我们的时钟或者水表一样,这一层的走了一圈,下一层的才走了一格。

 

类似手表的机制, 比较适合任务数量比较多的定时任务场景,它的任务写入和执行的时间复杂度都是 0(1)。

四.分布式任务

上述的大部分方案为单机情况下使用,如果需要分布式场景下的分片和高可用的话,需要用到分布式任务的调度框架。

涉及到下面的角色:

任务:执行的具体任务

调度器:需要有调度中心,任务由调度中心管理再分配

执行器:接受调度器执行任务

4.1 Quartz 

使用 Quartz 可以很方便地与 Spring集成,并且支持动态添加任务和集群。但是,Quartz 使用起来也比较麻烦,API 繁琐。

并且,Quartz 并没有内置 UI 管理控制台另外,Quartz 虽然也支持分布式任务。但是,它是在数据库层面,通过数据库的锁机制做的,有非常多的弊端比如系统侵入性严重、节点负载不均衡。有点伪分布式的味道。

优缺点总结:

  • 优点:可以与 Spring集成,并且支持动态添加任务和集群。
  • 缺点:分布式支持不友好,没有内置 UI 管理控制台、使用麻烦(相比于其他同类型框架来说)

4.2 Elastic-Job

优缺点总结:

  • 优点:可以与 Spring集成、支持分布式、支持集群、性能不错
  • 缺点:依赖了额外的中间件比如 Zookeeper(复杂度增加,可靠性降低、维护成本变高

4.2 xxlJob

优缺点总结:

  • 优点:开箱即用(学习成本比较低)、与 Spring 集成、支持分布式、支持集群、内置了 UI 管理控制台。
  • 缺点:不支持动态添加任务(如果一定想要动态创建任务也是支持的,参见:xxl-job issue277open in new window)。

引用

https://javaguide.cn/system-design/schedule-task.html#quartz