1. 任务调度定义
任务调度就是按照特定时间规则执行系统某个固定的业务逻辑。任务调度底层是使用jdk的Timer实现的。单体项目建议使用Spring-task任务调度技术,分布式架构建议使用quartz任务调度框架。Spring-task是单线程运行旳,Quartz是多线程运行的,且功能更为丰富,支持作业管理。
2. 任务调度技术及区别
2.1 Spring-task
使用场景:单体项目架构
特点:执行任务按照单线程运行,不会因为第一个执行任务时间过长而执行第二个;因为它是单线程的处理任务能力有限,不建议处理分布式架构的任务调度。
使用:执行任务只需要开启开关@EnableScheduling,在要执行的任务方法上加@Scheduled(cron = “*/1 * * * * *”)注解。
Cron表达式:有至少 6 个(也可能是 7 个)由空格分隔的时间元素。从左至右,这些元素的定义如下:
1.秒(0–59)
2.分钟(0–59)
3.小时(0–23)
4.月份中的日期(1–31)
5.月份(1–12 或 JAN–DEC)
6.星期中的日期(1–7 或 SUN–SAT)
7.年份(1970–2099)
注意:日期和星期只能出现一个
使用弊端:1. 任务A的执行时间会影响任务B的执行间隔,但是任务A和任务B是两个任务,不应该相互影响。
2.没有固定组件,持久化等功能,没法形成作业系统。
2.2 Quartz
使用场景:分布式项目架构使用Quartz
特点:多线程运行,支持持久化,多线程,集群模式,且有固定组件结构Job,Trigger,Scheduler。
优点:
- 有固定组件,有持久化功能,
这样就能基于Quartz开发一个任务调度系统,通过UI界面去管理任务调度。 - 任务进行持久化之后,重启服务器会加载持久化的任务继续执行。
- 任务支持集群模式,如果任务调度模块是一个集群n个节点,那么任务调度不会因为一个节点挂掉而挂掉,且任务在集群之间形成负载均衡。
Quartz 的核心类有以下三部分:
任务 Job : 需要实现的任务类,实现execute()
方法,执行后完成任务。
触发器 Trigger : 包括SimpleTrigger
和CronTrigger
。
调度器 Scheduler : 任务调度器,负责基于Trigger
触发器,来执行 Job任务。
3. 单线程与多线程执行任务调度的区别
3.1 单线程运行任务
单线程运行任务,不同任务之间串行,任务A运行时间会影响任务B运行间隔.
3.2 多线程执行任务
需要添加两个注解:
@DisallowConcurrentExecution:这个注解的作用就是同一个任务必须在上一次执行完毕之后,再按照corn时间执行,不会并行执行
@PersistJobDataAfterExecution:这个注解的作用就是下一个任务用到上一个任务的修改数据(定时任务里面的jobData数据流转)
结果:任务2还是1s执行一次,没有受到任务1执行时间干扰,这是任务2和任务1用的线程不同。
4. 任务调度持久化的好处
如果任务调度没有持久化,而任务又是基于动态设置,不是开机自启的,会有一个问题,服务重启之后设置的任务都会失效了。
如果任务整合持久化之后,设置的动态任务信息就会保存到数据库,开机自启就会加载这些数据库信息,就会按照原来的设置运行任务。
但是,一定要把建表配置注释掉,否则会删除原表重建表,导致数据消失。
#spring.quartz.jdbc.initialize-schema: always
#spring.quartz.job-store-type: jdbc