Elastic-Job分布式调度学习

  1. 概述

1.1 什么是任务调度?

为了自动完成特定任务,在约定的特定时刻去执行任务

例如 : 每天晚上8点发放优惠券,每天凌晨需要统一数据

1.2 为什么需要分布式调度?

  • 单机处理极限 : 我们使用SpringTask定时器也是可以做得到,但是单机的性能(CPU,内存,硬盘)始终有限,对于海量的数据处理会有一定的极限

  • 高可用 : 如果单机宕机了,单点故障导致整个任务调度无法使用,所以需要保证任务的高可用性

  • 防止重复执行 : 我们部署了多台服务器,每台服务器都有自己的一个定时任务,概率会出现重复执行任务

  1. Elastic-Job

2.1 什么是 Elastic-Job ?

  • 是一个开源的分布式调度框架

  • 两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成

  • 两个核心模块分布式调度和分布式数据分片

Elastic-Job分布式调度学习_第1张图片

2.2 Leader节点

  • 在Elastic-Job中,每个作业都有一个Leader节点

  • 用于协调该作业的分布式任务调度

  • 负责分发任务,参与任务的执行

  • 当Elastic-Job启动时,会通过分布式锁选出一个Leader节点,成为该作业的主节点,如果Leader节点出现了故障,则会重新选举出新的Leader节点

  • Elastic-Job通过Leader节点实现了分布式任务调度的高可用性

  1. 搭建Elastic-Job

  1. 添加Zookeeper依赖


    com.dangdang
    elastic-job-lite-core
    2.1.5
  1. 自定义任务类实现SimpleJob接口

/**
 * @author: 南瓜战士
 * @create-date: 2023/3/10 12:41
 * 任务类
 */
public class MyElasticJob implements SimpleJob {

    /**
     * 执行的定时任务
     * @param shardingContext
     */
    @Override
    public void execute(ShardingContext shardingContext) {
        System.out.println("定时任务开启: " + LocalDateTime.now());
    }
}
  1. 配置类

/**
 * @author: 南瓜战士
 * @create-date: 2023/3/10 12:47
 */
public class App {

    public static void main(String[] args) {
        new JobScheduler(createRegistryCenter(), createJobConfiguration()).init();
    }

    /**
     * 实现分布式协调的注册中心
     * CoordinatorRegistryCenter 主要功能
     * 1.注册任务 : 将任务信息注册到分布式协调器中
     * 2.管理任务节点 : 可以实现任务的动态调度和负载均衡等功能
     * 3.实现分布式锁 : 防止多个节点同时对任务进行操作导致数据的不一致性
     *
     * @return
     */
    private static CoordinatorRegistryCenter createRegistryCenter() {
        //配置zk地址,调度任务的组名
        ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration("localhost:2181", "elastic-job-demo");
        // 会话超时时间
        zookeeperConfiguration.setSessionTimeoutMilliseconds(100);
        // 注册
        CoordinatorRegistryCenter regCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
        regCenter.init();
        return regCenter;
    }

    /**
     * 创建作业配置
     * @return
     */
    private static LiteJobConfiguration createJobConfiguration() {
        // 定义作业核心配置
        JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder("MyElasticJob","0/3 * * * * ?",1).build();
        // 定义SIMPLE类型配置
        SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, MyElasticJob.class.getCanonicalName());
        // 定义Lite作业根配置
        LiteJobConfiguration simpleJobRootConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).build();
        return simpleJobRootConfig;
    }
}

测试

Elastic-Job分布式调度学习_第2张图片
  1. 运行单个程序,按照进行任务的调度

  1. 运行多个程序,查看是否只有一个实例进行任务调度

  1. 运行多个程序后,关闭其中一个,查看是否继续进行任务调度

  1. Zookeeper

4.1 什么是Zookeeper?

开源的分布式协调服务框架,提供了一些基本的分布式协调功能

选举,锁,命名式服务和分布式同步

4.2 Elastic-Job为什么使用Zookeeper不使用Nacos ?

  • 原先设计之初未考虑使用 Nacos 作为其分布式协调服务

  • Zookeeper 在分布式协调领域有较好的实践经验,具有稳定性高,可靠性好等优点

  • Zookeeper 的数据模型和 API 设计适合 Elastic-Job 的需求,可以很好地支持 Elastic-Job 的任务分片,节点注册,选举等分布式协调操作

  • Elastic-Job两者都可以集成使用

  1. 整合SpringBoot

  1. 添加依赖

    cn.wolfcode
    elastic-job-springboot
    1.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.3.RELEASE
    
    
        UTF-8
        UTF-8
        1.8
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            com.dangdang
            elastic-job-lite-spring
            2.1.5
        
        
            org.projectlombok
            lombok
        
    
  1. 任务调度配置类

/**
 * 任务调度配置类
 */
@Configuration
public class ElasticJobConfig
{
    @Autowired
    private MyJob job;
    /**
     * 创建注册中心
     * @param zookeeperUrl zk连接地址
     * @param groupName 唯一命名空间
     * @return
     */
    @Bean(initMethod = "init")
    public CoordinatorRegistryCenter registryCenter(@Value("${zookeeper.url}") String zookeeperUrl,
                                                    @Value("${zookeeper.groupName}") String groupName)
    {
        // zk的配置,配置连接和命名空间
        ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration(zookeeperUrl,groupName);
        // 设置zk的超时时间
        zookeeperConfiguration.setSessionTimeoutMilliseconds(100);
        // 创建注册中心
        ZookeeperRegistryCenter zookeeperRegistryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);

        return zookeeperRegistryCenter;
    }

    /**
     * 创建作业配置
     * @return
     */
    private static LiteJobConfiguration createJobConfiguration(Class clazz,String cron,int shardingTotalCount) {
        //        //        // 定义作业核心配置
        JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(clazz.getSimpleName(),cron,shardingTotalCount).build();
        // 定义SIMPLE类型配置
        SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, clazz.getCanonicalName());
        // 定义Lite作业根配置
        LiteJobConfiguration simpleJobRootConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).build();
        return simpleJobRootConfig;
    }

    /**
     * 创建一个任务调度
     * @param job 作业开发
     * @param rc 注册中心
     * @return
     */
    @Bean(initMethod = "init")
    public SpringJobScheduler jobScheduler(MyJob job,CoordinatorRegistryCenter rc)
    {
        // 作业配置
        LiteJobConfiguration jobConfiguration = createJobConfiguration(job.getClass(), "0/3 * * * * ?", 1);
        // 创建任务调度
        SpringJobScheduler springJobScheduler = new SpringJobScheduler(job,rc,jobConfiguration);
        // 返回任务调度
        return springJobScheduler;
    }
}
  1. 创建自定义任务调度(上面代码已经做了),这里只是详细指出

/**
     * 创建一个任务调度
     * @param myJob 作业开发
     * @param rc 注册中心
     * @return
     */
        @Bean(initMethod = "init")
        public SpringJobScheduler springJobScheduler(MyJob myJob,CoordinatorRegistryCenter rc)
        {
            // 作业配置
            LiteJobConfiguration jobConfiguration = createJobConfiguration(MyJob.class, "0/3 * * * * ?", 1);
            // 创建任务调度
            SpringJobScheduler springJobScheduler = new SpringJobScheduler(myJob,rc,jobConfiguration);
            // 返回任务调度
            return springJobScheduler;
        }

  1. 分片

6.1 分片概念

指任务的分布式执行,将一个任务划分成若干份

6.2 分片的规则

  • 按照业务进行划分

  • 分片数量 > 机器的数量,最大限度利用资源(推荐)

6.3 Dataflow 类型

  • 任务量很多的情况下,全部加载到内存中,内存溢出的问题

  • 零点开始执行,还会有数据发送过来

  • 分别用于抓取(fetchData)和处理(processData)

  • 用于处理数据流,和SimpleJob不同,以数据流的方式执行,调用fetchData抓取数据,抓取不到才会停止工作

6.4 Dataflow 和 Simple 作业类型的选择

  • Simple 适合处理较小的数据集或定期执行的任务,如数据同步,数据备份等

  • Dataflow 是一种基于数据流的处理任务,适合处理大量数据和复杂的数据处理任务,如数据清洗,数据分析,数据流作业,通过分片将数据分成多个小批次进行处理,提高任务处理速度

6.5 分片总结

  1. 例如我们分4片,两台机器,不给分片参数,Elastic-Job会帮我们自动分片,每台机器平均分两片

  1. 每个分片一个线程,一台服务器相当于一个进程,一台服务器一个进程,分到两个分配就是两个线程执行

  1. 分多少片就启动多少个线程

Elastic-Job分布式调度学习_第3张图片

你可能感兴趣的:(学习,zookeeper,分布式)