【面试中的分布式定时任务】

devtools/2025/3/20 4:08:14/

定时任务与分布式定时任务框架XXL-JOB详解

一、为什么需要定时任务?

定时任务在业务场景中非常常见,主要用于以下场景:

  1. 时间驱动处理
    • 整点发送优惠券
    • 每天更新收益
    • 每天刷新标签数据和人群数据

  2. 批量处理数据
    • 按月批量统计报表数据
    • 批量更新短信状态
    • 实时性要求不高的数据处理

  3. 异步执行解耦
    • 活动状态刷新
    • 数据同步
    • 异步执行离线查询,与内部逻辑解耦

二、定时任务的实现方式

定时任务的实现方式有多种,以下是常见的几种:

  1. JDK方式
    • 死循环
    • Timer定时器
    • JUC定时任务

  2. Spring Scheduling声明式定时任务
    @EnableScheduling
    @Scheduled

  3. 经典定时任务框架
    • Quartz

  4. 分布式定时任务
    • XXL-JOB(基于Quartz)
    • Elastic-Job(基于Quartz)
    • Saturn(Elastic-Job的Fork版本)

  5. MQ延时队列

三、各解决方案的优缺点

  1. JDK方式及Spring Scheduling
    • 优点:简单易用
    • 缺点:不支持高可用,不支持动态配置

  2. Quartz
    • 优点:支持高可用
    • 缺点:配置复杂(需要10几张表),不支持动态配置

  3. XXL-JOB
    • 优点:支持高可用,动态配置,任务统一管理
    • 缺点:需要额外部署调度中心

四、分布式定时任务框架XXL-JOB

XXL-JOB是一个分布式任务调度平台,核心设计目标是开发迅速、学习简单、轻量级、易扩展。目前已有多家公司接入,包括大众点评、京东、优信二手车等。

4.1 项目结构

XXL-JOB支持通过Web页面对任务进行CRUD操作,支持动态修改任务状态、暂停/恢复任务,以及终止运行中任务。

源码地址:
• GitHub:https://github.com/xuxueli/xxl-job
• 码云:http://gitee.com/xuxueli0323/xxl-job

项目结构如下:

xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor-samples:执行器示例
xxl-job-executor-sample-springboot:SpringBoot版本(推荐)
xxl-job-executor-sample-spring:Spring版本
xxl-job-executor-sample-frameless:无框架版本
• 其他版本:JFinal、Nutz、jboot等

4.2 设计思想

XXL-JOB将调度行为抽象为“调度中心”,调度中心负责发起调度请求,而任务逻辑由“执行器”处理。调度中心与执行器解耦,提高了系统的稳定性和扩展性。

4.3 部署调度中心

4.3.1 初始化调度数据库

执行tables_xxl_job.sql脚本初始化数据库。调度中心支持集群部署,集群节点需连接同一个MySQL实例。

4.3.2 修改调度中心配置

配置文件路径:xxl-job/xxl-job-admin/src/main/resources/application.properties
主要配置项:
• 端口号
• JDBC数据源
• 报警邮箱
• 调度中心通讯TOKEN

4.3.3 打包运行调度中心
  1. 编译打包:mvn clean package -Dmaven.skip.test=true
  2. 启动调度中心:java -jar xxl-job-admin-2.2.0.jar
  3. 访问调度中心:http://localhost:8080/xxl-job-admin

默认登录账号:admin/123456

4.3.4 调度中心集群(可选)

调度中心支持集群部署,提升系统的容灾和可用性。集群部署时需保证DB配置一致,机器时钟一致。

4.4 搭建执行器项目

执行器负责接收调度中心的调度并执行任务。可以将执行器集成到现有项目中,也可以直接使用示例项目。

4.4.1 添加XXL-JOB依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.2.0</version>
</dependency>
4.4.2 修改执行器配置

配置文件路径:xxl-job-executor-sample-springboot/src/main/resources/application.properties
主要配置项:
• 调度中心地址
• 执行器AppName
• 执行器端口号
• 日志存储路径

4.4.3 添加执行器配置类

Copy示例工程的配置文件到项目中,无需修改。

4.4.4 给执行器添加任务
@Component
public class MyJobHandler {@XxlJob("myJobHandler")public ReturnT<String> execute(String param) {XxlJobLogger.log("任务执行日志");System.out.println("任务执行:" + param);return ReturnT.SUCCESS;}
}
4.4.5 执行器管理

在调度中心“执行器管理”界面添加执行器,支持自动注册和手动录入。

4.5 任务界面详解

任务配置项包括:
• 执行器
• 任务描述
• 路由策略
• Cron表达式
• 运行模式(BEAN模式、GLUE模式)
• 阻塞处理策略
• 子任务
• 任务超时时间
• 失败重试次数
• 报警邮件
• 负责人
• 执行参数

4.6 分片广播任务

分片广播任务适用于大数据量处理场景,如分片任务、广播任务等。任务会广播到所有执行器,执行器根据分片参数处理数据。

@JobHandler(value="shardingJobHandler")
@Service
public class ShardingJobHandler extends IJobHandler {@Overridepublic ReturnT<String> execute(String param) {ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();XxlJobLogger.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardingVO.getIndex(), shardingVO.getTotal());return SUCCESS;}
}

五、使用XXL-JOB改造购物车数据同步

5.1 异步执行失败记录到Redis

改造CartAsyncExceptionHandler,将异常用户记录到Redis。

@Slf4j
@Component
public class CartAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String KEY = "cart:async:exception";@Overridepublic void handleUncaughtException(Throwable throwable, Method method, Object... objects) {log.error("异步调用发生异常,方法:{},参数:{},异常信息:{}", method, objects, throwable.getMessage());String userId = objects[0].toString();BoundListOperations<String, String> listOps = this.redisTemplate.boundListOps(KEY);listOps.leftPush(userId);}
}

5.2 添加任务同步购物车数据

在定时任务工程中引入Redis和Mapper接口,添加CartJobHandler任务。

@Component
public class CartJobHandler {@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate CartMapper cartMapper;private static final String KEY = "cart:async:exception";private static final String KEY_PREFIX = "cart:info:";@XxlJob("cartJobHandler")public ReturnT<String> executor(String param) {BoundListOperations<String, String> listOps = this.redisTemplate.boundListOps(KEY);String userId = listOps.rightPop();while (StringUtils.isNotBlank(userId)) {this.cartMapper.delete(new UpdateWrapper<Cart>().eq("user_id", userId));BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);List<Object> cartJsons = hashOps.values();if (!CollectionUtils.isEmpty(cartJsons)) {cartJsons.forEach(cartJson -> {this.cartMapper.insert(JSON.parseObject(cartJson.toString(), Cart.class));});}userId = listOps.rightPop();}return ReturnT.SUCCESS;}
}

六、总结

XXL-JOB是一个功能强大、易于使用的分布式任务调度框架,支持高可用、动态配置和任务统一管理。通过XXL-JOB,可以轻松实现定时任务的调度和执行,适用于各种业务场景。


http://www.ppmy.cn/devtools/168526.html

相关文章

A SURVEY ON POST-TRAINING OF LARGE LANGUAGE MODELS——大型语言模型的训练后优化综述——第一部分

arXiv 2025 摘要 大型语言模型&#xff08;LLMs&#xff09;的出现从根本上改变了自然语言处理&#xff0c;使其在从对话系统到科学研究的各个领域中变得不可或缺。然而&#xff0c;它们的预训练架构在特定情境下经常显示出局限性&#xff0c;包括有限的推理能力、伦理不确定…

docker 安装 nginx 部署Vue前端项目

1 安装 docker 安装docker详细步骤 安装docker报错解决方案 2 安装 nginx 2.1 拉取镜像 拉取1.18.0版本的镜像 docker pull nginx:1.18.0 查看镜像 2.2 创建实例并启动 创建并启动实例 # 随便启动一个nginx实例&#xff0c;只是为了复制出配置 docker run -p 80:80 --nam…

linux环境下快速输出电脑的系统/硬件/显卡/网络/已安装软件等信息

在Linux环境下&#xff0c;可以通过以下命令快速获取系统和硬件信息。最后将这些命令整合成一个脚本&#xff08;如 sysinfo.sh&#xff09;&#xff0c;一键输出所有信息。 1. 系统信息 # 内核信息 uname -a# 发行版信息 lsb_release -a 2>/dev/null || cat /etc/*release…

【在数轴上找最优位置,使移动距离最短】

L1-4 破碎的心&#xff0c;无法挽回的距离 题目描述: YFffffff 最近在感情上遭受了失败&#xff0c;他的心也破碎成了n块碎片&#xff0c;散落在了数轴上的 n 个位置。 你是一个情感修复师&#xff0c;作为 YFffffff 的好友&#xff0c;你试图将这些破碎的心重新聚集到一个位…

matlab 控制系统GUI设计-PID控制超前滞后控制

1、内容简介 matlab164-控制系统GUI设计-PID控制超前滞后控制 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略

Matlab 风力发电机磁悬浮轴承模型pid控制

1、内容简介 略 Matlab 174-风力发电机磁悬浮轴承模型pid控制 可以交流、咨询、答疑 2、内容说明 磁悬浮轴承具有无接触、无摩擦、高速度、高精度、能耗低、不需要需润滑无油污染、可靠性高、寿命长和密封等一系列显著的优点。将磁悬浮技术应用于风力发电机中可以降低风机切入…

`FisherTrainer` 的自定义 `Trainer` 类:累积梯度的平方并求平均来近似计算 Fisher 信息矩阵

FisherTrainer 的自定义 Trainer 类:累积梯度的平方并求平均来近似计算 Fisher 信息矩阵 用于计算模型参数的 Fisher 信息矩阵的近似值 整体目标 Fisher 信息矩阵用于衡量模型参数的不确定性,其在优化问题中可以帮助我们更准确地更新模型参数,避免陷入局部最优。在代码中,…

玩转ChatGPT:Claude 3.7 Sonnet进行数据分析(ARIMA)

一、写在前面 上一期&#xff0c;我们测试了Claude 3.7 Sonnet在机器学习分类建模的能力。 这一期&#xff0c;我们来测试一下它的数据回归的潜力。 首先试一试最经典的ARIMA模型。 二、开测 &#xff08;1&#xff09;Project功能 Claude 的 Project 功能是一个很有用的工…