如何设计一个定时任务?
一.日常工作中使用到的框架?
单机: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 issue277 )。
引用
https://javaguide.cn/system-design/schedule-task.html#quartz