1. XXL-Job 的重点内容
XXL-Job 是一款分布式任务调度框架,核心解决是解决分布式环境下任务的统一调度、负载均衡和高可用问题,其重点内容包括:
-
核心组件
- 调度中心(Admin):集中管理任务配置、触发调度、监控执行状态,支持集群部署(基于数据库实现分布式锁保证一致性)。
- 执行器(Executor):部署在业务服务中,接收调度中心指令并执行任务,支持集群部署(自动注册到调度中心)。
- 任务(Job):业务逻辑载体,支持 BEAN 模式(类方法)和 GLUE 模式(动态脚本)。
-
核心特性
- 分布式调度:突破单机限制,任务可在多执行器间分发。
- 分片执行:大任务按规则拆分(如 100 万条数据拆分为 10 个分片),并行处理。
- 弹性扩容:执行器集群动态增减时,任务自动重新分配。
- 失败重试:支持失败后自动重试(可配置次数和间隔)。
- 监控报警:任务状态可视化,支持邮件、钉钉等报警方式。
- 日志追踪:执行日志集中存储,支持在线查看。
2. XXL-Job 各类策略及含义
(1)路由策略(任务分配到哪个执行器)
决定任务请求发送到哪个执行器实例:
- 第一个:固定选择第一个在线执行器。
- 最后一个:固定选择最后一个在线执行器。
- 轮询:按顺序依次分配给每个执行器(负载均衡常用)。
- 随机:随机选择执行器(适合无状态任务)。
- 一致性 HASH:相同参数的任务始终分配给同一执行器(适合有状态任务,如分片数据处理)。
- 最不经常使用(LFU):优先分配给历史负载最低的执行器。
- 最近最久未使用(LRU):优先分配给最近最少被使用的执行器。
- 故障转移:优先选择健康的执行器(跳过故障实例)。
- 分片广播:所有执行器都接收任务,但仅处理自己负责的分片(分片任务专用)。
(2)阻塞处理策略(任务触发时前一次未执行完)
- 单机串行:等待前一次执行完成后再执行新任务(默认)。
- 丢弃后续调度:若任务阻塞,直接丢弃新的调度请求。
- 覆盖之前调度:用新任务覆盖正在执行的旧任务(适合实时性要求高的场景)。
(3)失败处理策略(任务执行失败后)
- 失败告警:仅触发报警,不重试。
- 失败重试:按配置的重试次数自动重试(重试间隔可配置)。
(4)触发策略(任务何时执行)
- CRON 表达式:基于时间的灵活调度(如每天凌晨 2 点执行)。
- 固定间隔:按固定时间间隔触发(如每隔 30 分钟)。
- 固定延迟:上一次执行完成后延迟固定时间触发(如执行完延迟 10 分钟)。
- 手动触发:通过控制台手动触发执行。
3. Java 引入 XXL-Job 的流程
(1)部署调度中心(Admin)
- 下载源码:从 XXL-Job 官网 获取最新版本。
- 初始化数据库:执行
doc/db/tables_xxl_job.sql创建调度中心所需表。 - 配置调度中心:修改
application.properties中的数据库连接和端口(默认 8080)。 - 启动调度中心:运行
XxlJobAdminApplication主类。
(2)项目引入依赖
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version> <!-- 需与调度中心版本一致 -->
</dependency>
(3)配置执行器
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class XxlJobConfig {
@Value("${xxl.job.admin.addresses}")
private String adminAddresses; // 调度中心地址
@Value("${xxl.job.executor.appname}")
private String appname; // 执行器名称(需与控制台配置一致)
@Value("${xxl.job.executor.port:9999}")
private int port; // 执行器端口
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
XxlJobSpringExecutor executor = new XxlJobSpringExecutor();
executor.setAdminAddresses(adminAddresses);
executor.setAppname(appname);
executor.setPort(port);
// 可选:配置日志路径、访问令牌等
return executor;
}
}
(4)配置文件(application.properties)
# 调度中心地址(多个用逗号分隔)
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
# 执行器名称(唯一标识)
xxl.job.executor.appname=my-executor
# 执行器端口(默认 9999,多实例需不同)
xxl.job.executor.port=9999
(5)编写任务处理器
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;
@Component
public class MyJobHandler {
// 任务标识:需与控制台配置的 JobHandler 一致
@XxlJob("myShardingJob")
public void execute() throws Exception {
// 任务逻辑
System.out.println("执行分片任务...");
}
}
(6)控制台配置任务
- 登录调度中心(默认账号 admin/123456)。
- 新增执行器:配置执行器名称(与
appname一致)。 - 新增任务:填写任务名称、执行器、JobHandler(与
@XxlJob注解值一致)、路由策略、分片参数等。
4. XXL-Job 在 Sharding-JDBC 中的分片执行
Sharding-JDBC 负责数据分片存储(如按 id%10 分 10 张表),XXL-Job 按相同规则拆分任务,实现分布式并行处理。
(1)Sharding-JDBC 分表配置(以 10 张表为例)
spring:
shardingsphere:
datasource:
names: ds_1
ds_1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db?useSSL=false
username: root
password: 123456
rules:
sharding:
tables:
user:
actual-data-nodes: ds_1.user_${0..9} # 10 张分表
table-strategy:
standard:
sharding-column: id # 分片键
sharding-algorithm-name: user_inline
sharding-algorithms:
user_inline:
type: INLINE
props:
algorithm-expression: user_${id % 10} # 分表规则
(2)XXL-Job 分片任务实现
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserSyncJob {
@Autowired
private UserService userService;
// 任务标识:与控制台配置一致
@XxlJob("userSyncJob")
public void syncUserToEs() {
// 获取分片参数(控制台配置分片参数为 0-9)
int shardIndex = XxlJobHelper.getShardIndex(); // 当前分片索引(0-9)
int shardTotal = XxlJobHelper.getShardTotal(); // 总分片数(10)
try {
// 按分片同步数据(规则与 Sharding-JDBC 一致:id%10=shardIndex)
long count = userService.syncByShard(shardIndex);
XxlJobHelper.handleSuccess("分片" + shardIndex + "同步完成,处理" + count + "条");
} catch (Exception e) {
XxlJobHelper.handleFail("分片" + shardIndex + "失败:" + e.getMessage());
}
}
}
(3)Service 层实现分片查询
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private EsClient esClient;
// 按分片同步数据
public long syncByShard(int shardIndex) {
// Sharding-JDBC 自动路由到 user_${shardIndex} 分表
List<User> users = userMapper.selectByShard(shardIndex);
if (!users.isEmpty()) {
esClient.bulkInsert(users); // 批量写入 ES
}
return users.size();
}
}
(4)Mapper 层查询
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
// 按分片查询(where 条件与分表规则一致)
@Select("SELECT * FROM user WHERE id % 10 = #{shardIndex}")
List<User> selectByShard(@Param("shardIndex") int shardIndex);
}
(5)控制台配置分片任务
- 分片参数:
0-9(总分片数 10)。 - 路由策略:分片广播(确保所有执行器接收任务)。
5. XXL-Job 使用注意事项
-
分片策略一致性
- XXL-Job 分片数必须与 Sharding-JDBC 分表数一致,否则会出现数据漏处理或重复处理。
- 分片规则(如
id%10)必须完全相同,确保任务与数据分片对齐。
-
执行器集群部署
- 执行器端口需唯一(避免冲突),建议通过
-Dxxl.job.executor.port=9999动态指定。 - 执行器名称(
appname)必须一致,否则调度中心无法识别为同一集群。
- 执行器端口需唯一(避免冲突),建议通过
-
任务幂等性
- 任务可能因重试、网络波动等重复执行,需确保业务逻辑幂等(如基于
id去重)。
- 任务可能因重试、网络波动等重复执行,需确保业务逻辑幂等(如基于
-
资源控制
- 单个任务避免处理过大数据量,建议分页批量处理(如每次 500 条)。
- 配置合理的线程池参数(执行器默认核心线程数为 20),避免线程耗尽。
-
日志与监控
- 生产环境关闭 SQL 日志(
sql-show: false),避免性能损耗。 - 配置任务超时时间(如 300 秒)和失败报警,及时发现异常。
- 生产环境关闭 SQL 日志(
-
版本兼容性
- 执行器与调度中心版本必须一致,否则可能出现通信异常。
-
动态扩容
- 新增执行器后,调度中心会自动发现,任务会重新负载均衡。
- 分表扩展时,需同步调整 XXL-Job 分片参数(如从 10 改为 11)并迁移数据。
2559

被折叠的 条评论
为什么被折叠?



