分布式任务调度xxl-job

**1.**概述

1.1****什么是任务调度

我们可以思考一下业务场景的解决方案:
某电商平台需要每天上午10点,下午3点,晚上8点发放一批优惠卷
某银行系统需要在信用卡到期还款日的前三天进行短信提醒
某财务系统需要在每天凌晨0:10分结算前天的财务数据,统计汇总
以上场景都需要任务调度所解决

1.2****为什么需要?

感觉spring给我们提供的这个注解可以完成任务调度的功能,但是为什么要分布式的呢?

  1. 高可用:单机版的定时任务调度只能在一台机器上运行,如果程序或系统出现异常就会导致功能不可用。
  2. 防止重复执行:在单机模式下,定时任务是没什么问题的。但当我们部署了多台服务,同时又每台服务又有定时任务时,若不进行合理的控制在同一时间,只有一个定时任务启动执行,这时定时执行的结果就可能存在混乱和错误。
  3. 单机处理极限:原本1分钟需要处理1w订单,但是现在需要1min处理1w订单,原来一个统计需要1d,现在业务方需要10min统计,单机的CPU是有限的,多线程处理也不一定可以满足。

1.3 xxl-job****介绍

xxl-job:是大众点评的分布式任务调度平台,是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展
大众点评目前已经接入xxl-job,该系统在内部已调度100w次,表现优异。

系统架构图

**2.**快速入门

2.1****简单配置

  1. 先下载源码,上csdn查
  2. 在项目的doc文件可以查看项目的架构等信息,先执行sql脚本
  3. 修改xxl-job-admin的application文件
    修改连接的数据库

    修改定时任务执行时,任务失败发送邮件、短信,可扩展钉钉

    访问路径

    设置好了启动项目,项目的默认账号密码是:admin/123456

2.2****配置部署执行器项目

2.2.1添加maven****依赖

XML 复制代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0-SNAPSHOT</version>
</dependency>

注意:xxl-job-core的版本要看上面下载的项目的版本号

2.2.2编写配置和config

XML 复制代码
# web port
server.port=8081
### 调度中心部署跟地址[选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址
进行"执行器心跳注册"和"任务结来回调",为空则关闭
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
#### 执行器通讯TOKEN[选填]:非空时启用
xxl. job.accessToken=default token
####执行器AppName[选填]:执行器心跳注册分组依据:为空则关闭自动注册
xxl.job.executor.appname=xxl-job-executor-sample
### 执行器注册[选填]:优先使用该配置作为注册地址,为空时使用内服务IP:PORT "作为注册地址。从而
更灵活的支持容器类型执行器动态IP和动态映射
xxl.job.executor.address=
#### 执行器IP [选填]:默认为空表示自动获取1P,多网卡时可手动设置指定1P,该1P不会绑定Host仅作
为通讯实用;地址信息用于"执行器注册"和"调度中心请
xxl.job.executor.ip=127.0.0.1
#### 执行器端口号[选填]:小于等于0则自动获取:默认端口为9999,单机部署多个执行器时,注意要配置不
同执行器端口;
xxl.job.executor.port=9999
#### 执行器运行日志文件存储磁盘路径[选填]:需要对该路径拥有读写权限:为空则使用默认路径
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
#### 执行器日志文件保存天数[选填]:过期日志自动清理,限制值大于等于3时生效,否则,如-1,关闭自
动清理功能
xxl.job.executor.logretentiondays=30
java 复制代码
package com.example.xxljobdemo.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* xxl-job config
*
* @author xuxueli 2017-04-28
*/
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
/**
* 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils"
组件灵活定制注册IP;
*
* 1、引入依赖:
* <dependency>
* <groupId>org.springframework.cloud</groupId>
启动项目我们可以看到
2.2.3 编写定时任务
* <artifactId>spring-cloud-commons</artifactId>
* <version>${version}</version>
* </dependency>
*
* 2、配置文件,或者容器启动变量
* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
*
* 3、获取IP
* String ip_ =
inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
*/
}

启动项目我们可以看到

2.2.3****编写定时任务

java 复制代码
package com.example.xxljobdemo.job;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class SampleXxlJob {
private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);
@XxlJob("demoJobHandler")
public void demoJobHandler() {
System.out.println("执行定时任务,执行时间" + new Date());
}
}

在操作中启动任务

2.3 GLUE模式(java)

任务以源码方式维护在调度中心,支持通过web ide在线更新,实时编译和生效,因此不需要指定
jobHandler。
运行模式的任务实际上是一段继承自IjobHandler的java类代码,它在执行器项目中运行,可使用
@Resource/@Autowired注入执行器里的其他服务

添加****service

新增任务

改使用方法2,注意可以回滚版本

2.6****执行器集群

2.6.1****集群环境搭建

在idea设置springboot项目运行并开启多个集群


查看效果的话,需要根据任务编辑里面的路由策略:

  • 第一个:固定选择第一个执行器
  • 最后一个:固定选择最后一个执行器
  • 轮询:依次选择在线的执行器发起调度
  • 随机:随机选择在线的执行器一致性hash:每个任务按照hash算法固定选择某一台机器,且所有任务均匀散列在不同的机器上。
  • 最不经常使用:使用频率最低的机器优先被选举
  • 最近最久未使用:最久未使用的机器优先被选举
  • 故障转移:按照顺序依次进行心跳检测,第一个心跳检测成功的机器选定为目标执行器并发起调度
  • 忙碌转移:按照顺序一次进行空闲检测,第一个空闲检测成功的机器选定为目标执行并发起调度
  • 分片广播:广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数,可根据分片参数开发分片任务

**3.**分片功能讲解

3.1****案例需求讲解

需求:在指定节假日,需要给平台的所有用户去发送祝福的短信

初始化数据

在数据库中导入xxl_job_demo.sql 数据(用户的基本信息)

添加依赖

添加配置

添加实体类

添加mapper处理类

3.1.3 业务功能实现



重新启动项目
设置任务

3.2****分片概念理解

比如我们的案例中有2000+数据,如果不采取分片形式的话,任务只会在一台机器上执行,这样的话需要20+秒才能完成任务
如果采取分片广播的形式的话,一次任务调度将会广播触发对应集群中所有执行器执行一次任务,同时系统自动传递分片参数,可根据分片参数开发分片任务

我们将2000的数据,根据id分成奇数和偶数,给到上面两台机器进行执行



相关推荐
文丑颜不良啊12 小时前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang13 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪14 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息14 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼15 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发
SL_staff16 小时前
JVS-BI 实战:业务人员如何用零代码 ELT + 可视化配置构建实时经营分析闭环
java·spring·全栈
SL_staff16 小时前
企业AI落地难?JVS-AI渐进式实践:安全可控、小切口验证、标准化沉淀与规模化复制
java·开源·aigc
Alluxio17 小时前
Alluxio + OCI:为 AI 工作负载实现亚毫秒访问延迟与可扩展吞吐
运维·数据库·人工智能·分布式·缓存·ai·语言模型
SL_staff17 小时前
JVS数字底座实践:构建企业级统一内容管理平台的技术路径
java·产品
nice_lcj52018 小时前
【从零理解 Spring AI · 12】MCP 的两种角色:做客户端还是做服务端
java·后端·spring·spring ai·ai应用开发