Elastic-Job分布式任务调度_学习笔记01

# 1.任务调度的实现方式 ## 多线程方式实现: 学过多线程的同学,可能会想到,我们可以开启一个线程,每sleep一段时间,就去检查是否已到预期执行时间。 以下代码简单实现了任务调度的功能: ```java public static void main(String[] args) { //任务执行间隔时间 final long timeInterval = 1000; Runnable runnable = new Runnable() { public void run() { while (true) { //TODO:something try { Thread.sleep(timeInterval); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread thread = new Thread(runnable); thread.start(); ``` 上面的代码实现了按一定的间隔时间执行任务调度的功能。 Jdk也为我们提供了相关支持,如Timer、ScheduledExecutor,下边我们了解下。 ## Timer方式实现: ```java public static void main(String[] args){ Timer timer = new Timer(); timer.schedule(new TimerTask(){ @Override public void run() { //TODO:something } }, 1000, 2000); //1秒后开始调度,每2秒执行一次 } ``` Timer 的优点在于简单易用,每个Timer对应一个线程,因此可以同时启动多个Timer并行执行多个任务,同一个 Timer中的任务是串行执行。 ## ScheduledExecutor方式实现: ```java public static void main(String [] agrs){ ScheduledExecutorService service = Executors.newScheduledThreadPool(10); service.scheduleAtFixedRate( } new Runnable() { @Override public void run() { //TODO:something System.out.println("todo something"); } }, 1, 2, TimeUnit.SECONDS); } ``` Java 5 推出了基于线程池设计的 ScheduledExecutor,其设计思想是,每一个被调度的任务都会由线程池中一个 线程去执行,因此任务是并发执行的,相互之间不会受到干扰。 Timer 和 ScheduledExecutor 都仅能提供基于开始时间与重复间隔的任务调度,不能胜任更加复杂的调度需求。 比如,设置每月第一天凌晨1点执行任务、复杂调度任务的管理、任务间传递数据等等。 Quartz 是一个功能强大的任务调度框架,它可以满足更多更复杂的调度需求,Quartz 设计的核心类包括 Scheduler, Job 以及 Trigger。其中,Job 负责定义需要执行的任务,Trigger 负责设置调度策略,Scheduler 将二 者组装在一起,并触发任务开始执行。Quartz支持简单的按时间间隔调度、还支持按日历调度方式,通过设置 CronTrigger表达式(包括:秒、分、时、日、月、周、年)进行任务调度。 ## 第三方Quartz方式实现 ```java public static void main(String [] agrs) throws SchedulerException { //创建一个Scheduler SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); //创建JobDetail JobBuilder jobDetailBuilder = JobBuilder.newJob(MyJob.class); jobDetailBuilder.withIdentity("jobName","jobGroupName"); JobDetail jobDetail = jobDetailBuilder.build(); //创建触发的CronTrigger 支持按日历调度 CronTrigger trigger = TriggerBuilder.newTrigger() .withIdentity("triggerName", "triggerGroupName") .startNow() .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) .build(); //创建触发的SimpleTrigger 简单的间隔调度 /*SimpleTrigger trigger = TriggerBuilder.newTrigger() .withIdentity("triggerName","triggerGroupName") .startNow() .withSchedule(SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(2) .repeatForever()) .build();*/ scheduler.scheduleJob(jobDetail,trigger); scheduler.start(); } public class MyJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext){ System.out.println("todo something"); } } ``` 通过以上内容我们学习了什么是任务调度,任务调度所解决的问题,以及任务调度的多种实现方式。 # 2.分布式调度要实现的目标 不管是任务调度程序集成在应用程序中,还是单独构建的任务调度系统,如果采用分布式调度任务的方式就相当于 将任务调度程序分布式构建,这样就可以具有分布式系统的特点,并且提高任务的调度处理能力: 1、并行任务调度 并行任务调度实现靠多线程,如果有大量任务需要调度,此时光靠多线程就会有瓶颈了,因为一台计算机CPU的处 理能力是有限的。 如果将任务调度程序分布式部署,每个结点还可以部署为集群,这样就可以让多台计算机共同去完成任务调度,我 们可以将任务分割为若干个分片,由不同的实例并行执行,来提高任务调度的处理效率。 2、高可用 若某一个实例宕机,不影响其他实例来执行任务。 3、弹性扩容 当集群中增加实例就可以提高并执行任务的处理效率。 4、任务管理与监测 对系统中存在的所有定时任务进行统一的管理及监测。让开发人员及运维人员能够时刻了解任务执行情况,从而做 出快速的应急处理响应。 5、避免任务重复执行 当任务调度以集群方式部署,同一个任务调度可能会执行多次,比如在上面提到的电商系统中到点发优惠券的例 子,就会发放多次优惠券,对公司造成很多损失,所以我们需要控制相同的任务在多个运行实例上只执行一次,考 虑采用下边的方法: 分布式锁,多个实例在任务执行前首先需要获取锁,如果获取失败那么久证明有其他服务已经再运行,如果 获取成功那么证明没有服务在运行定时任务,那么就可以执行。 ![image.png](https://images.codewd.com/1d867f5307972d121f4cfeec45c4c3b6.png) ZooKeeper选举,利用ZooKeeper对Leader实例执行定时任务,有其他业务已经使用了ZK,那么执行定时任 务的时候判断自己是否是Leader,如果不是则不执行,如果是则执行业务逻辑,这样也能达到我们的目的。 ![image.png](https://images.codewd.com/8e7e6c5fea20e32d065bbea9dbcc52bd.png) # 3 Elastic-Job介绍 针对分布式任务调度的需求市场上出现了很多的产品: 1)Elastic-job:当当网基于quartz 二次开发的弹性分布式任务调度系统,功能丰富强大,采用zookeeper实现分 布式协调,实现任务高可用以及分片。 2)Saturn: 唯品会开源的一个分布式任务调度平台,可以全域统一配置,统一监控,任务高可用以及分片并发处 理。它是在elastic-job基础之上改良出来的。 3)xxl-job:大众点评的分布式任务调度平台,是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学 习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。 4)TBSchedule:淘宝的一款非常优秀的高性能分布式调度框架,目前被应用于阿里、京东、支付宝、国美等很多 互联网企业的流程调度系统中。 Elastic-Job是一个分布式调度的解决方案,由当当网开源,它由两个相互独立的子项目Elastic-Job-Lite和Elastic- Job-Cloud组成,使用Elastic-Job可以快速实现分布式任务调度。 Elastic-Job的github地址:[https://github.com/elasticjob](https://github.com/elasticjob) ## 功能列表 分布式调度协调 在分布式环境中,任务能够按指定的调度策略执行,并且能够避免同一任务多实例重复执行。 丰富的调度策略 基于成熟的定时任务作业框架Quartz cron表达式执行定时任务。 弹性扩容缩容 当集群中增加某一个实例,它应当也能够被选举并执行任务;当集群减少一个实例时,它所执行的任务能被 转移到别的实例来执行。 失效转移 某实例在任务执行失败后,会被转移到其他实例执行。 错过执行作业重触发 若因某种原因导致作业错过执行,自动记录错过执行的作业,并在上次作业完成后自动触发。 支持并行调度 支持任务分片,任务分片是指将一个任务分为多个小任务项在多个实例同时执行。 作业分片一致性 当任务被分片后,保证同一分片在分布式环境中仅一个执行实例。 支持作业生命周期操作 可以动态对任务进行开启及停止操作。 丰富的作业类型 支持Simple、DataFlow、Script三种作业类型,后续会有详细介绍。 Spring整合以及命名空间支持 对Spring支持良好的整合方式,支持spring自定义命名空间,支持占位符。 运维平台 提供运维界面,可以管理作业和注册中心。 # 4 Elastic-Job快速入门 ## 版本要求 JDK要求1.7及以上版本 Maven要求3.0.4及以上版本 zookeeper要求采用3.4.6及以上版本