Elastic-job 分布式任务调度原理「建议收藏」

Elastic-job 分布式任务调度原理「建议收藏」什么是任务调度?任务调度是指系统为了自动完成特定任务,在约定的特定的时刻去执行任务的过程。有了任务调度即可解放更多的人力系统自动去执行任务。任务

欢迎大家来到IT世界,在知识的湖畔探索吧!

什么是任务调度?

任务调度是指系统为了自动完成特定任务,在约定的特定的时刻去执行任务的过程。有了任务调度即可解放更多的人力系统自动去执行任务。

任务调度如何实现?

1. 多线程方式实现

实现一个按一定间隔的时间执行任务调度的功能。

简单代码实现:

public static void main(String[] args) {
    // 任务执行的时间间隔
    final long timeInterval = 1000;
    Runable runable = new Runable(){
          public void run() {
               while(true) {
                   try {
                     Thread.sleep(timeInterval);
                   } catch (Exception e){
                      e.printStackTrace();
                   }
               }
          } 
    };
}

欢迎大家来到IT世界,在知识的湖畔探索吧!

JDK也为我们提供了相关的支持,如Timer、ScheduledExecutor

2. Timer方式实现(定时器)

欢迎大家来到IT世界,在知识的湖畔探索吧!public static void main (String[] args) {
  Timer timer = new Timer();
  timer.schedule(new TimerTask(){
        @Override
        public void run(){
           //TODO:业务代码
        }
  },1000,2000); //1秒后开始调度,每2秒执行一次
}

Timer的优点在于简单易用,每个Timer对应一个线程,因此可以同时启动多个Timer并行执行多个任务,同是一个Timer中的任务是串行执行。

3. ScheduleExecutor方式实现:

public static void main(String[] args) {
  ScheduleExecutorService service = Executors.newScheduledThreadPool(10);
  service.scheduleAtFixedRate(
      new Runable() {
         @Override
         public void run() {
            //TODO:something
            System.out.println("");
         }
      },1,2,TimeUnit.SECONDS);
  )
}

Java5推出了基于线程池设计的ScheduleExecutor,其设计思想是,每一个被调度的任务都会由线程池中一个线程去执行,因此任务是并发执行,相互之间是互不干涉。

4. 第三方的Quartz实现

欢迎大家来到IT世界,在知识的湖畔探索吧!public static void main() {
  // 创建一个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();
  scheduler.scheduleJob(jobDetail,trigger);
  scheduler.start();
}

什么是分布式?

分布式架构就是将单体的系统架构分为若干个服务,通过网络交互来相互通信。

例如:电商系统为分布式架构,由订单服务,商品服务,用户服务等组成。

分布式的特点:

1. 分布式

2. 伸缩性

3. 高可用

什么是分布式任务调度?

指的是在分布式系统的环境下运行任务调度,我们称之为分布式任务调度

由于采用了分布式架构,一个服务往往会部署多个冗余实例来运行我们的业务。

分布式调度实现的目标:

1. 并行任务调度

并行任务实现靠多线程,如果有大量任务需要调度,此时光靠多线程就会有瓶颈,因为一台计算机CPU的处理能力是有限的。如果将任务调度程序分布式部署,每一个节点还可以部署为集群,这个就可以让多台计算机共同去完成任务调度,我们可以将任务分割为若干个分片,由不同的实例并行执行,来提高任务调度的处理效率。

2. 高可用

若某一个实例宕机,不影响其他的实例来执行任务。

3. 弹性扩容

当集群中增加实例就可以提高并执行任务的处理效率。

4. 任务管理和监测

对系统中存在的所有定时任务进行统一的管理及监测,让开发人员及运维人员能够时刻了解任务执行情况,从而做出快速的应急处理响应。

5. 避免任务重复执行

当任务调度以集群的方式部署,同一个任务可能会执行多次,比如电商系统中到店发优惠券的例子,就会发放多次优惠券,多公司造成很多损失,所以我们需要控制相同的任务在多个运行实例上执行一次,考虑采用下边的方法:

* 分布式锁,多个实例子在任务执行前首先需要获取锁,如果获取失败那么久证明已经有其他的服务已经在运行了,如果获取成功没有服务在运行定时任务,那么就可以执行。

* Zookeeper选举,利用Zookeeper对leader实例执行定时任务,有其他业务已经使用了,那么执行定时任务的时候判断自己是否是leader,如果不是则不执行,如果是则执行业务逻辑,这样也能达到我们的目的。

Elastic-job介绍

Elastic-job是分布式调度的解决方案,由当当网开源,它由两个相互独立的子项目Elastic-job-Lite和Elastic-job-Cloud组成,使用Elastic-job可以快速实现分布式任务调度。

功能列表:

* 分布式调度协调

在分布式环境中,任务能够按指定的调度策略执行,并且能够避免同一个任务多实例重复执行。

* 丰富的调度策略

基于成熟的定时任务作业框架Quartz cron表达式执行定时任务。

* 弹性扩容和缩容

当集群中增加一个实例,它应当也能够被选举并执行任务,当集群减少一个实例时,它所执行的任务能被转移到别的实例来执行。

* 失效转移

某实例在任务执行失败后,能够转移到其他的实例执行。

* 支持并行调度

支持任务分片,任务分片指的是将一个任务分我多个小任务项在多个实例同时执行。

* 作业分片一致性

当任务被分片后,保证同一个分片在分布式环境中仅有一个实例执行。

* 支持作业生命周期操作

可以动态对任务进行开启以及停止操作。

Elastic-job整体的架构?

Elastic-job 分布式任务调度原理「建议收藏」

什么是作业分片?

分片的概念:

作业分片是指任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的应用实例分别执行一个或者几个分片项。

例如:Elastic-job快速入门中文件备份的例子,现有2台服务器,每台服务器分别跑一个应用实例。为了快速的执行作业,那么可以将作业分成4片每个应用实例执行2片,作业遍历数据的逻辑应为:实例1查询text和iamge类型文件执行备份,实例2查找radio和video类型文件备份。如果由于服务器扩容应用实例数量增加为4,则作业遍历数据的逻辑应为:4个实例分别处理text,image,radio,video类型的文件通过对任务的合理分片化,从而达到任务并行处理的效果,最大限度的提高执行作业的吞吐量。

* 分片项与业务处理解耦

Elastic-job并不是直接提供数据处理的功能,框架只会将分片项分配到各个运行中的作业服务器,开发者需要自行处理分片项与真实数据对应的关系。

* 最大限度利用资源

将分片项设置为大于服务器的数量,最好是大于服务器倍数的数量,作业将会合理地利用分布式资源,动态的分配分片项

面试题:Elastic-job分片的原理?

elastic-job的分片是通过zookeeper来实现的,而分片是由主节点分配,如下三种情况都会触发主节点的分片算法执行:

1. 新的job实例加入集群

2. 现有的job实例下线(如果下线的是leader节点,那么先选举然后触发分片算法的执行)

3. 主节点选举

Elastic-job 分布式任务调度原理「建议收藏」

上述三种情况,会让zookeeper上leader节点的sharding节点上多出来一个necessary的临时节点,主节点每次执行job前,都会去看一下这个节点,如果有则执行分片算法。

分片执行结果会存储在zookeeper上,如下图,5个分片,每个分片应该由哪个job实例来运行都已经分配好。分配过程就是上面触发分片算法之后的操作,分配完成之后,各个job实例就会在下次执行的时候使用上这个分配的结果。

Elastic-job 分布式任务调度原理「建议收藏」

每个job实例任务触发前都会获取本任务在本实例上的分片情况,然后封装成shardingContext,传递给调用任务的实际执行方法:

void execute(ShardingContext shardingContext); 

分片算法?

所有的分片策略都继承JobShardingStrategy接口。根据当前注册到ZK的实例列表和在客户端配置的分片数量来进行数据分片。最终将每个Job实例应该获得的分片数字返回出去。 方法签名如下:

/**
     * 作业分片.
     * 
     * @param jobInstances 所有参与分片的单元列表
     * @param jobName 作业名称
     * @param shardingTotalCount 分片总数
     * @return 分片结果
     */
    Map<JobInstance, List<Integer>> sharding(List<JobInstance> jobInstances, String jobName, int shardingTotalCount);

分片函数的触发,只会在leader选举的时候触发,也就是说只会在刚启动和leader节点离开的时候触发,并且是在leader节点上触发,而其他节点不会触发。

1. 基于平均分配算法的分片策略,也就是默认的分片策略

如果分片不能整除,则不能整除的多余分片将依次追加到序号小的服务器。

缺点是:一旦分片数小于作业服务器数,作业将永远分配到ip地址靠前的服务器,导致ip地址靠后的服务器空闲。

2. 根据作业名的哈希值奇偶数决定ip升降序算法的分片策略

作业名的哈希值为奇数则ip升序,作业名的哈希值为偶数则ip降序。

3. 根据作业名的哈希值对服务器列表进行轮转的分片策略

4. 自定义分片策略的原理

主要实现JobShardingStrategy接口,并且把该类配置到分片方法上去。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/12909.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信