定时任务框架

常用定时任务框架

  1. JDK 自带的 ScheduledExecutorService

    • 适用于轻量级定时任务,基于线程池实现。
    • API 简单,适用于小规模任务调度。
  2. Quartz

    • 强大的 Java 任务调度框架,支持 Cron 表达式、分布式集群、持久化等。
    • 适用于复杂调度场景,如动态任务管理、任务持久化等。
  3. Spring Task

    • Spring 提供的轻量级定时任务方案,支持 @Scheduled 注解,简洁易用。
    • 适用于简单的定时任务,不支持集群和分布式调度。
  4. XXL-JOB

    • 轻量级分布式任务调度框架,支持集群、动态管理任务、任务日志、失败重试等功能。
    • 适用于互联网企业的大规模定时任务场景。
  5. Elastic-Job

    • 基于 Zookeeper 的分布式任务调度框架,支持分片、失效转移、任务高可用等特性。
    • 适用于大规模分布式任务调度,如电商、金融等业务场景。
  6. PowerJob

    • 基于 Spring Boot 开发的分布式任务调度框架,支持分布式、秒级调度、任务依赖等功能。
    • 适用于现代分布式任务管理,支持 Web 可视化管理。

分布式定时任务框架

如果你的项目被 多个相同实例的 Pod 复制 并部署在 Kubernetes 集群中,那么使用普通的 @ScheduledScheduledExecutorService 就会导致 每个 Pod 都会执行同一个定时任务,可能会产生 重复任务执行 的问题。为了解决这个问题,你可以选择 支持分布式调度 的定时任务框架,主要有以下几种推荐方案:

1. Elastic-Job(推荐)

  • 适用场景:适用于 微服务架构,可基于 Zookeeper 进行任务分片,实现分布式调度。
  • 特点
    • 分片执行:不同 Pod 执行任务的不同部分,避免重复执行。
    • 任务失效转移:某个 Pod 宕机后,任务会自动转移给其他 Pod 继续执行。
    • 支持高可用:基于 Zookeeper 进行任务协调,防止重复执行。
  • 适用于
    • 高并发业务,如订单对账、数据同步、日志清理等。
    • 需要保证每个任务只执行一次,或按分片方式执行的场景

2. XXL-JOB

  • 适用场景:适用于 Spring Boot + 集群环境,提供一个 调度中心 统一管理任务,避免重复执行。
  • 特点
    • 基于调度中心(Admin)统一管理定时任务。
    • 任务分片:可配置多个 Pod 执行不同的任务片段,防止重复执行。
    • 失败重试:任务失败后可自动重试。
    • 可视化管理:Web 界面配置任务,支持动态修改。
  • 适用于
    • 需要 Web 可视化管理任务的场景
    • 希望任务分布式执行,并能动态调整任务执行策略

Elastic-Job 示例代码

下面是 Elastic-Job 在分布式集群环境下的完整示例代码,基于 Spring Boot + Zookeeper,实现了 分布式定时任务调度

功能概述

  • 采用 Spring Boot + Elastic-Job-Lite 实现分布式定时任务。
  • 任务注册到 Zookeeper,保证 多个实例(Pod)不会重复执行同一任务,可实现 任务分片
  • 适用于 Kubernetes、Docker Swarm普通分布式集群环境

配置 Zookeeper

application.yml 中配置 Elastic-Job 连接 Zookeeper

spring:
  application:
    name: elastic-job-demo

elasticjob:
  reg-center:
    server-lists: zk-host:2181  # 替换为你的 Zookeeper 地址
    namespace: elastic-job-demo  # 在 Zookeeper 创建的命名空间
  jobs:
    demoJob:
      cron: "0/10 * * * * ?"  # 每 10 秒执行一次
      sharding-total-count: 3  # 任务分片总数,多个实例共同执行任务
      overwrite: true  # 是否覆盖旧任务

编写定时任务

新建 分片任务,继承 SimpleJob,实现 execute() 方法:

import org.apache.shardingsphere.elasticjob.api.ShardingContext;
import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;
import org.springframework.stereotype.Component;

@Component
public class MyElasticJob implements SimpleJob {

    @Override
    public void execute(ShardingContext shardingContext) {
        // 获取当前分片编号
        int shardingItem = shardingContext.getShardingItem();
        String jobName = shardingContext.getJobName();

        // 模拟不同分片处理不同数据
        switch (shardingItem) {
            case 0:
                System.out.println("【分片 0】执行任务:" + jobName);
                break;
            case 1:
                System.out.println("【分片 1】执行任务:" + jobName);
                break;
            case 2:
                System.out.println("【分片 2】执行任务:" + jobName);
                break;
            default:
                System.out.println("【未知分片】执行任务:" + jobName);
        }
    }
}

注册任务

创建 ElasticJobConfig,将任务注册到 ElasticJob

import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
import org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.ScheduleJobBootstrap;
import org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.OneOffJobBootstrap;
import org.apache.shardingsphere.elasticjob.lite.api.listener.ElasticJobListener;
import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticJobConfig {

    private final ZookeeperRegistryCenter regCenter;
    private final MyElasticJob myElasticJob;

    public ElasticJobConfig(ZookeeperRegistryCenter regCenter, MyElasticJob myElasticJob) {
        this.regCenter = regCenter;
        this.myElasticJob = myElasticJob;
    }

    @Bean
    public ScheduleJobBootstrap initElasticJob() {
        JobConfiguration jobConfig = JobConfiguration.newBuilder("myElasticJob", 3)
                .cron("0/10 * * * * ?")  // 每 10 秒执行
                .overwrite(true)  // 覆盖旧任务
                .build();

        return new ScheduleJobBootstrap(regCenter, myElasticJob, jobConfig);
    }
}

配置 Zookeeper 注册中心

创建 ZookeeperConfig 以连接 Zookeeper

import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperConfiguration;
import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ZookeeperConfig {

    @Bean(initMethod = "init")
    public ZookeeperRegistryCenter regCenter() {
        return new ZookeeperRegistryCenter(
                new ZookeeperConfiguration("zk-host:2181", "elastic-job-demo")
        );
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值