定时任务之Quartz和Elastic-Job
一、背景
常用的定时任务一般有:JDK Timer、Spring Task、Quartz、xxl-job、Elastic-job。
JDK Timer:JDK自带的定时任务,1.5之前不支持多线程,1.5之后加入了ScheduleThreadPool就是为了它,支持多线程;
Spring Task:Spring的定时任务,但是不支持集群;
Quartz:简单、轻量级最常用的定时任务,支持集群;
xxl-job、Elastic-job:xxl-job是京东的一个架构师开发的定时任务,Elastic-job是当当网开源的一个定时任务,两者都是基于Quartz开发的。
二、Quartz
1、Quartz主要有三个重要的组件:schedule、job、trigger,其中schedule是调度器,job就是我们要执行的任务,trigger是任务的触发时间。其中job和trigger是1:N的关系,一个job可以绑定多个时间触发。
2、trigger一共是四种:SimpleTrigger:固定时刻,固定时间间隔(毫秒) 、CalendarIntervalTrigger:时间单位、DailyTimeIntervalTrigger、CronTrigger:Cron表达式。
3、可以对job设置开启时间,但是怎么排除一些时间呢,可以用Calendar,设置不同的时间,然后进行排除。Calendar包括:AnnualCalendar 、CronCalendar 、DailyCalendar 、HolidayCalendar、MonthlyCalendar 、WeeklyCalendar。
4、Quartz有监听器,分别是jobListener、scheduleListener、triggerListener,可以针对三者进行监听,当三者发生变动均可通过对应的监听器获取数据。
5、jobstore:持久化,默认持久化到内存,可修改成持久化到jdbc。
6、由于Quartz是一个容器,Spring也是一个容器,因此在Quartz中不能通过注入的方式直接拿到spring中的bean。可以通过自定义JobFactory生成Job,然后在生成Job的最后将Job放入spring容器中,然后将自定的jobFactory设置为job的factory就行了。
7、Quartz支持集群,在配置文件中配置集群相关的参数即可开启集群模式,集群中只有一个节点能跑某一个任务,不会出现任务的重跑,当一个节点挂了,集群中的其他节点会有一个继续跑定时任务,保证不漏跑。
原因:Quartz默认通过数据库表的方式来设置锁,数据库中有一个表专门来存锁字段,多个节点的调度器会执行一个sql来获取锁,获取到锁的节点执行定时任务。获取锁的sql是利用select for update来锁的,执行完以后提交事务就释放锁,碰到异常会回滚事务也释放锁。也可用zk或者redis来实现,quartz默认用DB实现的。
三、Elastic-Job
1、Elastic-Job是当当开源的,其也是在Quartz的基础上进行二次封装使得更加的便捷好用。
2、 Elastic-Job目前分为两个版本,一个是Elastic-Job-Lite,一个是Elastic-Job-Cloud,其实二者的api是一样的就是部署方式不一样而已,通过名字就能看出来Elastic-Job-Cloud是针对于微服务的部署方式的。Elastic-Job依赖zk作为注册中心进行任务的分布式调度协调。
3、Elastic-Job的特性
3.1:使用zk作为注册中心进行分布式调度协调以及节点的选举;
3.3:错过执行的作业重新执行(misfire);
3.4:支持并发(任务分片,同一个任务可以分成多片同时执行);
3.5:作业分片一致性,同一个时间点集群中同一个分片只有一个实例执行;
3.6:动态扩缩容:集群进行运行时会根据分片分配不同的任务,任务执行过程中当有新机器加入或者现有机器下线,那么elastic-job将保持现有作业不变的情况下继续执行,在下次再次执行任务之前会重新进行任务的分片;
3.7:失效转移:集群会在机器发生变化以后再次执行任务时重新分片,但是本次执行任务的过程中下线机器对应的任务不会继续被执行。但是失效转移可以利用空闲机器来执行孤儿任务,但是这会牺牲部分性能;
4.8、通过Listener支持作业周期内操作作业;
3.9、丰富的作业类型(Simple、DataFlow数据流、Script脚本)
3.10、有自己的运维平台,可监控任务的执行
4、Elastic的使用分为三步,整合到springboot中也是分为三步,分别是配置core、type、lite
core配置:配置zk地址、作业名称、cron表达式、分片总数;
type配置:配置作业的类型,Simple、DataFlow、Script选择一种作业的类型;
lite配置:配置lite部署或者cloud部署的一些参数配置,也可以配置分片的策略;
5、因为使用了zk作为注册中心,故节点信息、数据的配置、分片的信息都能在zk的节点上看到;
6、运维平台的使用
源码地址:https://github.com/elasticjob/elastic-job-lite,到该地址上找到elastic-job-lite-console打包,然后到本地进行解压并执行bin/start.sh,访问localhost:8899,账号密码是root/root,即可访问控制台。
7、分片策略:例如有100个任务,刚才设置的是10个分片总数,那么其实分片项就是10,如果机器为5,那么每个机器分配的就是2个分片项。可以设置不用的分片策略,也可以自定义,具体哪些分片策略可以去官网看。
三、特殊情况处理
1、什么情况下会导致任务错过触发,两个任务调度器都是怎么处理的?
没有可用的线程、Trigger被暂停、系统重启、禁止并发执行的任务在到达触发时间时,上次执行还没结束。
Quartz:每个trigger都有自己的MisFire策略,不同的策略通过不同的方法来执行,策略大致分为三种:忽略、立即跑一次、下次再跑。
Elastic-Job:错过的作业下次重新执行。
2、如何避免任务错过触发?
合理设置线程池数量以及任务触发间隔。
原文链接:https://blog.csdn.net/xiaoye319/article/details/106343126