大家好,欢迎来到IT知识分享网。
什么是任务调度?
在了解分布式任务调度之前,首先我们需要知道什么是任务调度?现在思考这样几个场景。
- 有一个系统,需要下午18:00举行一个活动。
- 当你领取了某商场的消费券的时候,需要在到期三天之前提醒你消费
- 银行核心系统需要在每天凌晨三点做结算操作
- 618、双十一商家需要定时发送优惠券
- ……
当然这样的场景会有很多,面对这样的问题很多人就会想到使用定时任务,也就是任务调度去解决。
所谓的任务调度,就是由系统自动去完成某些特定的任务,系统会根据约定的规则在指定的时间去执行一些特定的任务。这样可以在极大程度上减少了人工工作的压力。
如何去实现任务调度呢?
相信很多人都见过这样的代码,这个代码所完成的的功能就是让线程每隔一段时间去执行一次,厉害吧,还有更绝的就是每个24小时执行一次,开发者就把当前的线程Sleep的时间改成24*60*6000,绝了吧
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早就为我们提供了定时任务有关的方法,只不过在我们学习Java基础的时候没有认真听讲罢了。
例如我们可以使用Timer来实现定时任务。
public static void main(String[] args){ Timer timer = new Timer(); timer.schedule(new TimerTask(){ @Override public void run() { //TODO:something } }, 1000, 2000); //1秒后开始调度,每2秒执行一次 }
或者使用ScheduledExecutor的方式来实现任务调度。
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); }
可以看出以上两种方式都可以完成任务的调度。但是会发现,以上的两种方式只能完成在一段时间内定时执行的任务,而无法完成指定时间的任务调度。这该如何是好呢?难道要像上面一样,使用Thread.sleep么?其实不然,下面我们就来介绍几种任务调度的框架。
Quartz任务调度框架
从上面的例子中,我们可以知道,Timer、ScheduledExecutor可以完成一些简单的定时任务的执行调度,但是对于一些复杂的任务调度操作确实很难实现,这个时候,我们就需要使用到Quartz任务调度框架。
Quartz核心设计包括Scheduler、Job以及Trigger等等,其中Job就是用来执行定时任务的具体操作而Trigger则是负责来设计执行的策略也就是说什么时候执行,执行多少次。而Scheduler则是将两者组合到一起共同来完成定时任务操作。
Quartz通过Cron表达式来确定如何去执行定时任务。具体操作有兴趣的读者可以查看相关文档。这里篇幅有限,就不做过多示例。
什么是分布式任务调度?
通常如上面所说的那种情况,定时任务都是在单体应用中去执行的。例如定时发布活动、定时发布优惠券等等操作。但在分布式系统中由于系统是分布式部署的,一个服务往往会存在多个实例的情况,这种在分布式系统中运行的任务调度的情况被称为是分布式任务调度。如下图所示。
分布式任务调度所面临的问题
在分布式系统情况下设计一个任务调度管理需要面对各种各样的问题。
- 当任务以集群方式部署的时候,同一个调度任务可能会被多次重复执行。例如如果要定期发放优惠券,如果多个实例中出现重复执行的任务,就有可能会出现重复发放优惠券的情况。
- 如何能够在不去重启服务的情况下实现对于定时任务的动态调整。例如一个活动,因为要临时修改开始时间,所以要动态对于开始时间进行调整
- 如果存在定时任务的节点发生故障之后,如何能够快速的将任务执行转移到其他节点上,或者是对故障进行快速的解决。
- 如何能够实现对任务执行情况的实时监控
- 如何能够在单节点出现瓶颈的时候,进行快速扩容操作
- 如何能够合理的实现定时任务的拆分,如下图所示。
这些问题都是我们在设计分布式任务调度的时候需要去考虑的问题。例如可以使用分布式锁来解决重复执行问题,可以使用配置文件、或者是Redis KV存储结构来存储任务调度的时间,这样可以保证动态时间调整等等。
分布式调度框架
- TBSchedule:基于ZooKeeper的纯Java实现,由Alibaba开源
- Elastic-job:当当网基于quartz 二次开发的弹性分布式任务调度系统,功能丰富强大,采用zookeeper实现分布式协调,实现任务高可用以及分片。Elastic-Job是一个分布式调度的解决方案,由当当网开源,它由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成,使用Elastic-Job可以快速实现分布式任务调度。
- XXL-JOB:xxl是xxl-job的开发者大众点评的许雪里名称的拼音开头。其核心设计目标是:学习简单、开发迅速、轻量级、易扩展。
总结
上面我们介绍了定时任务以及分布式任务调度。其实分布式任务调度的核心就是如何能够保证在同一时刻只有一个任务执行,以及如何对一个大任务进行拆分,在解决这两个根本问题的时候就会出现各种各样的小问题,当我们将问题全部解决之后,就实现了分布式任务调度。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/159426.html