# task-scheduling **Repository Path**: flowerAndJava/task-scheduling ## Basic Information - **Project Name**: task-scheduling - **Description**: 从单体定时任务到分布式集群任务调度平台搭建。 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2021-05-09 - **Last Updated**: 2022-05-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # task-scheduling **开源源码** timer-demo模块:Timer定时案例; scheduledExecutor-demo模块:为ScheduledExecutor线程池定时任务; springboot-scheduled模块:SpringBoot自带的定时任务; quartz-monomer-demo模块:quartz实现单体任务调度; quartz-cluster-demo模块:quartz搭建集群任务调度; spring-elasticjob模块:spring集成elasticjob; elasticjob-springboot-starter模块:自定义elasticjob启动类; elasticjob-test模块:springboot使用elasticjob测试定时任务; **知识模块** 参考下方文档; # 一 corn 代表任务执行时间 ## 1.1 corn长度 ```$xslt 例如: 0 * * * * ? 七个域 秒 分 时 日 月 星期 年 六个域(常用) 秒 分 时 日 月 星期 ``` ## 1.2 每个域取值 ```$xslt 域 允许值 允许的特殊字符 秒 0-59 , - * / 分 0-59 , - * / 小时 0~23 , - * / 日 1-31 , - * / ? L W 月 1-12 or JAN-DEC , - * / 周 1-7 or SUN-SAT , - * / ? L # 年 1970-2099 , - * / 备注: 每个域允许上面数字和特殊应字符。'-'代表数字取值范围 ','代表枚举 '*'代表任意数字' '/'代表递增。 '?'当表示月的第几天,周需要用'?'。当表示周的第几天,月用'?'。 案例: 0 0 10 * * ? 每天10点触发一次 0 */1 * * * ? 每隔1分钟执行一次 0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发  0 0 17 ? * TUES,THUR,SAT 每周二、四、六下午五点 ``` ## 1.3 在线生成corn表达式生成校验 ```$xslt https://cron.qqe2.com/ ``` # 二 Timer JDK提供的任务调度。每个Timer对应一个线程,因此可以同时启动多个Timer并行执行多个任务,同一个Timer中的任务是串行执行。 已经被ScheduledExecutor替换掉了,知道有Timer就行。 # 三 ScheduledExecutor Java 5 推出了基于线程池设计的定时任务。每个定时任务会从线程池中取出一个线程执行,并发执行,互不干扰。 **总结** Timer和ScheduledExecutor只能执行延时多久,并以一定的周期来执行。复杂的任务调度不能完成。 # 四 Quartz 支持复杂的定时任务。支持集群,不支持分布式。 ## 1.4.1 概述 **1. 核心角色(Trigger,JobDetail ,Scheduler)** Trigger:定义调度规则 JobDetail:封装job,job定义具体业务。 Scheduler:将Trigger和JobDetail注册到Scheduler。Scheduler根据Trigger规则调用JobDetail中业务。 **2. 单体任务调度使用** 配置文件中配置scheduler名称 定义job类继承QuartzJobBean 在配置类中定义JobDetail、Triggerd对象 ## 1.4.2 集群服务搭建(需要mysql分布式锁) **1. 集群环境,如何防止任务重复执行?** a 每个quartz服务只有一个Scheduler实例 b Scheduler实例要想执行任务,需要qrtz_locks表中行锁; 锁被占用:等到其他Scheduler释放锁; 获取到锁:获取qrtz_triggers表中Waiting状态,并且即将出发的trigger; 将Trigger状态由Waiting修改为Acquired; 将trigger信息插入qrtz_fire_triggers表; c qrtz_fired_triggers修改为executing; 执行Job;修改qrtz_triggers中下次触发时间;将状态修改为Waiting; **2. 故障判断** 每个Quartz服务中Scheduler会定时更新qrtz_scheduler_state表中的LAST_CHECK_TIME字段。当集群中有 一个Scheduler更新时,会检查其它的Scheduler是否按预期更新,如果为否,认为节点故障。 **3. 失败迁移** 删除qrtz_scheduler_state表中对应的schedular信息,将任务可以由其他schedular执行; # 五 Elastic-job(重要,经常使用) 支持分布式任务调度技术。 **1. 使用步骤(参考elasticjob-test代码参考引用)** a 安装Zookeerper注册中心 b 导入elasticjob启动类(就是代码elasticjob-springboot-starter模块) c 自定义监听器、分片规则(直接使用默认分片规则) c 编写任务类 **2. 名词讲解** Elastic-Job-lite 以jar包形式提供轻量级的分布式任务; 依赖zookeeper: 分布式协调和任务信息管理;; 分片:定时任务执行最小单位; 一个项目分成几片,这个定时任务方法就执行几次。所以你可能存在疑问,那不就造成任务重复执行。 我们处理自己的业务,将任务分到不同的分片。然后将分片放到不同的服务。即实现分布式调度, 而且还不会重复执行任务。 **3. 高级特性** 作业分片 elasticjob自定义平均分片略,我们也可以自定义分片策略。需要继承JobShardingStrategy。(具体实现参考elasticjob-test模块代码) 弹性扩容 新增一个服务。zookeeper监听到新的服务注册进来,服务重新选举主节点,主节点调用分片策略,从新分片到各个服务上。 失效转移 片分布到若干个服务器上,如果其中一个服务死机了,则该服务分片会被别的服务抢占。保证任务完整性。开启,failover="true" 幂等性 一个任务准备执行,但是上次定时任务还没执行完毕。这次任务不执行,等待下次任务执行。monitorExecution=true,开启幂等性。 **获取Java相关,请扫描二维码(公众号)** ![公众号](https://images.gitee.com/uploads/images/2021/0517/114318_529a43da_8390550.png "屏幕截图.png")