XXL-JOB 定时任务——从 Docker 部署到分片广播,分布式任务调度落地

XXL-JOB 定时任务——从 Docker 部署到分片广播,分布式任务调度落地
Scheduled单机跑跑还行多实例部署了就全乱了——哪个实例执行重复执行怎么办数据怎么分片并行处理XXL-JOB 就是专治这些的调度中心统一管任务执行器集群自动注册分片广播把大数据量拆成 N 份给 N 台机器并行跑。这篇文章从 Docker 部署、Spring Boot 3.x 整合到分片广播、任务参数、失败处理、父子任务链全部用一个完整流程串下来。安装可以去官网下载源码然后编译部署这里我只介绍使用 docker 部署docker 安装先去 github 官网找到 xxl_job 的 SQL 文件注意要去找对应版本的 sql 文件不要找 master 下的。在 MySQL 数据库中执行目前最新版要求 MySQL 要 8.0 以上执行完后会创建一个新的数据库名为xxl_job下载之前可以去 docker hub 搜索 xxl-job-admin 查看最新版dockerpull m.daocloud.io/docker.io/xuxueli/xxl-job-admin:3.4.2dockerrun-d\--nameidle-store-xxl-job-admin\-p8095:8080\-eTZAsia/Shanghai\-eJAVA_OPTS-Xms256m -Xmx512m\-ePARAMS--spring.datasource.urljdbc:mysql://host.docker.internal:3306/xxl_job?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseSSLfalse \ --spring.datasource.usernameroot \ --spring.datasource.passwordHliu1026. \ --xxl.job.accessTokenidle_store_xxl_job_2026\-v/Users/ice/Desktop/cola/code/docker/xxl-job/logs:/data/applogs\xuxueli/xxl-job-admin:3.4.2之后访问 http://locahost:8095可以看到控制台默认用户名 admin账号密码 123456Spring Boot 3.x 整合配置之前我们先来到控制台它这里的执行器管理里面有一个执行器默认案例我们编辑一下这个改成我们自己想要的名字选择自动注册就可以。然后在项目中在 pom.xml 中引入依赖dependencygroupIdcom.xuxueli/groupIdartifactIdxxl-job-core/artifactIdversion3.4.2/version/dependency版本和下载的 XXL-JOB 保持一致之后进行配置在 application.yaml 配置文件中配置内容xxl:job:adminAddresses:http://localhost:8095# xxl-job 调度中心部署根地址如调度中心集群部署存在多个地址则用逗号分隔accessToken:idle_store_xxl_job_2026# 和 xxl-job 上创建的 token 保持一致appName:xxl-job-executor-idle-store# 和 xxl-job 上创建的执行器名称保持一致ip:# 执行器 ip, 为空表示自动获取 ipport:9999# 执行器端口号logPath:./log/xxl-job/jobhandler# 执行器日志存放路径logRetentiondays:30# 日志保留时间单位天然后创建两个配置类一个读取配置一个初始化执行器ConfigurationProperties(prefixXxlJobProperties.PREFIX)ComponentDatapublicclassXxlJobProperties{publicstaticfinalStringPREFIXxxl.job;privateStringadminAddresses;privateStringaccessToken;privateStringappName;privateStringip;privateintport;privateStringlogPath;privateintlogRetentionDays30;}ConfigurationSlf4jpublicclassXxlJobConfig{ResourceprivateXxlJobPropertiesxxlJobProperties;/** * 初始化执行器 */BeanpublicXxlJobSpringExecutorxxlJobExecutor(){log.info( xxl-job config init.);XxlJobSpringExecutorxxlJobSpringExecutornewXxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(xxlJobProperties.getAdminAddresses());xxlJobSpringExecutor.setAppname(xxlJobProperties.getAppName());xxlJobSpringExecutor.setIp(xxlJobProperties.getIp());xxlJobSpringExecutor.setPort(xxlJobProperties.getPort());xxlJobSpringExecutor.setAccessToken(xxlJobProperties.getAccessToken());xxlJobSpringExecutor.setLogPath(xxlJobProperties.getLogPath());xxlJobSpringExecutor.setLogRetentionDays(xxlJobProperties.getLogRetentionDays());returnxxlJobSpringExecutor;}}配置完后启动项目如果成功注册的话在控制台就能查看到了 ip 端口写第一个任务之后来到任务管理这里面就可以配置我们执行器要执行的任务了这里选中后进行编辑配置完之后点击保存回到我们的服务中创建/job包存放定时任务比如我创建一个CreateTableXxlJob类定义如下ComponentpublicclassCreateTableXxlJob{XxlJob(createTableJobHandler)publicvoidcreateTableJobHandler()throwsException{XxlJobHelper.log(# 初始化明日增量数据表...);}}这里的createTableJobHandler对应前面的JobHandler。通过XxlJobHelper.log打印日志这样在管理后台能看到日志信息在控制台中我们可以自己运行定时任务可以选择运行一次或者启动(根据我们调度类型执行比如我这里就是5秒执行一次)。我们选择启动然后查询日志如果你有梯子可能会查询日志失败需要改一下配置文件中的ip改为本机IP比如我这里ip:172.25.64.42控制台配置任务调度类型类型说明示例无不自动调度只能手动触发临时任务CRON按 Cron 表达式周期性触发0 0 2 * * ?每天凌晨 2 点固定速度固定间隔秒为单位60每 60 秒一次任务配置运行模式任务以 JobHandler 方式维护在执行器端需要结合 “JobHandler” 属性匹配执行器中任务JobHandler 对应执行器中开发的任务类方法上XxlJob注解自定义的 value 值路由策略多实例怎么分配任务策略行为FIRST固定选第一台ROUND轮询RANDOM随机FAILOVER心跳检测选第一个活着的SHARDING_BROADCAST分片广播所有机器都执行传分片参数调度过期策略忽略调度过期后忽略过期的任务从当前时间开始重新计算下次触发时间立即执行一次调度过期后立即执行一次并从当前时间开始重新计算下次触发时间阻塞处理策略任务堆积怎么办调度过于密集执行器来不及处理时的处理策略单机串行默认调度请求进入单机执行器后调度请求进入FIFO队列并以串行方式运行丢弃后续调度调度请求进入单机执行器后发现执行器存在运行的调度任务本次请求将会被丢弃并标记为失败覆盖之前调度调度请求进入单机执行器后发现执行器存在运行的调度任务将会终止运行中的调度任务并清空队列然后运行本地调度任务任务超时时间支持自定义任务超时时间任务运行超时将会主动中断任务失败重试次数支持自定义任务失败重试次数当任务失败时将会按照预设的失败重试次数主动进行重试分配广播分片广播是 XXL-JOB 最值钱的功能。比如凌晨 2 点需要处理全量用户数据——10 万条部署了 3 台实例每台各分 3.3 万条并行处理ComponentpublicclassDataAlignXxlJob{XxlJob(dataAlignJobHandler)publicvoiddataAlignJobHandler(){// 拿到分片参数intshardIndexXxlJobHelper.getShardIndex();// 当前分片0, 1, 2intshardTotalXxlJobHelper.getShardTotal();// 总分片数3XxlJobHelper.log(当前分片: {}/{},shardIndex,shardTotal);// 按分片取数据每台机器只取自己那一段// SELECT * FROM user WHERE id % #{shardTotal} #{shardIndex}ListUserusersuserMapper.selectByShard(shardIndex,shardTotal);for(Useruser:users){// 处理逻辑...}XxlJobHelper.handleSuccess(分片 shardIndex 处理完成共 users.size() 条);}}用XxlJobHelper.getShardIndex()和getShardTotal()拿到分片信息SQL 里用WHERE id % shardTotal shardIndex做数据分片。3 台机器各处理 1/3提速 3 倍。控制台把这个任务的路由策略改成SHARDING_BROADCAST即可。任务参数控制台传参动态调整逻辑控制台 “任务参数” 里填的内容代码里能拿到XxlJob(dataAlignJobHandler)publicvoiddataAlignJobHandler(){StringparamXxlJobHelper.getJobParam();// batchSize500,startId10000// 解析参数动态调整}适合控制每次处理的批量大小、起止 ID 这些需要临时调整的参数——改控制台不用改代码。成功/失败标记XxlJob(myJobHandler)publicvoidmyJobHandler(){try{// 业务逻辑XxlJobHelper.handleSuccess(处理完成共 1000 条);}catch(Exceptione){XxlJobHelper.handleFail(处理失败: e.getMessage());}}不手动调的话默认算成功。handleSuccess和handleFail的参数会显示在控制台日志最前面方便快速看到执行结果。父子任务——任务链控制台配置 “子任务ID” 后当前任务执行成功时自动触发子任务。适合有先后依赖的场景——比如先同步数据 → 重建索引任务 A每天凌晨 2 点同步数据CRON: 0 0 2 * * ? ↓ 执行成功后自动触发 任务 B重建 Elasticsearch 索引调度类型无只被 A 触发