XXL-Job分布式任务调度

1.提出场景

目前,我们的定时任务都是基于SpringTask来实现的。但是SpringTask存在一些问题:

  • 当微服务多实例部署时,定时任务会被执行多次。而事实上我们只需要这个任务被执行一次即可。
  • 我们除了要定时创建表,还要定时持久化Redis数据到数据库,我们希望这多个定时任务能够按照顺序依次执行,SpringTask无法控制任务顺序(×)

不仅仅是SpringTask,其它单机使用的定时任务工具,都无法实现像这种任务执行者的调度、任务执行顺序的编排、任务监控等功能。这些功能必须要用到分布式任务调度组件。

2.原理[统一管理]

我们先来看看普通定时任务的实现原理,一般定时任务中会有两个组件:

  • 任务:要执行的代码
  • 任务触发器:基于定义好的规则触发任务

因此在多实例部署的时候,每个启动的服务实例都会有自己的任务触发器,这样就会导致各个实例各自运行,无法统一控制:

image-20240830171522168

如果我们想统一控制各服务实例的任务执行和调度—>统一控制[统一出发、统一调度]

事实上,大多数的分布式任务调度组件都是这样做的:

image-20240830172305858

这样一来,具体哪个任务该执行,什么时候执行,交给哪个应用实例来执行,全部都有统一的任务调度服务来统一控制。并且执行过程中的任务结果还可以通过回调接口返回,让我们方便的查看任务执行状态、执行日志。这样的服务就是分布式调度服务

3.技术对比

能够实现分布式任务调度的技术有很多,常见的有:【越往右越牛逼】

Quartz XXL-Job SchedulerX PowerJob
定时类型 CRON 频率、间隔、CRON 频率、间隔、CRON、OpenAPI 频率、间隔、CRON、OpenAPI
任务类型 Java 多语言脚本 多语言脚本 多语言脚本
任务调度方式 随机 单机、分片 单机、广播、Map、MapReduce 单机、广播、分片、Map、MapReduce
管理控制台 支持 支持 支持
日志白屏 支持 支持 支持
报警监控 支持 支持 支持
工作流 有限 支持 支持

其中:

  • Quartz由于功能相对比较落后,现在已经很少被使用了。
  • SchedulerX是阿里巴巴的云产品,收费。
  • PowerJob是阿里员工自己开源的一个组件,功能非常强大,不过目前市值占比还不高,还需要等待市场检验。
  • XXL-JOB:开源免费,功能虽然不如PowerJob,不过目前市场占比最高,稳定性有保证。

==———–XXL-Job———–==

1.XXL-Job介绍

image-20240829165652242

XXL-JOB分为两部分:

  • 执行器:我们的服务引入一个XXL-JOB的依赖,就可以通过配置创建一个执行器。负责与XXL-JOB调度中心交互,执行本地任务。
  • 调度中心:一个独立服务,负责管理执行器、管理任务、任务执行的调度、任务结果和日志收集。

其中,我们可以打开xxl-job页面:

  • 页面:
image-20240829165442027

2.XXL-Job部署[调度中心]

自己部署,分为两步:

  • 运行初始化SQL,创建数据库表
  • 利用Docker命令,创建并运行容器

2.1 创建数据库表

sql语句在对应github文件夹下:

image-20240830173817398

2.2 Docker部署

docker命令:

1
2
3
4
5
6
7
8
9
10
docker run \
-e PARAMS="--spring.datasource.url=jdbc:mysql://192.168.150.101:3306/xxl_job?Unicode=true&characterEncoding=UTF-8 \
--spring.datasource.username=root \
--spring.datasource.password=123" \
--restart=always \
-p 28080:8080 \
-v xxl-job-admin-applogs:/data/applogs \
--name xxl-job-admin \
-d \
xuxueli/xxl-job-admin:2.3.0

3.XXL-Job实战

3.1 需求

每10s打印一次hello…

3.2 实现步骤

image-20240829170153373

3.2.1 引入xxl-job依赖(微服务)

image-20240829170654201

1
2
3
4
5
<!--xxl-job-->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>

3.2.2 yml配置xxl-job(微服务)

  • 配置文件内容【nacos共享文件地址】

image-20240829170954454

  • 配置文件【因为我们使用nacos配置,所以需要bootstrap.yml配置nacos共享文件地址】
image-20240829171353854
  • 配置类
image-20240829172008280

3.2.3 配置执行器类–XxlJobConfig(微服务)

image-20240829172105476
1
2
3
4
5
6
- adminAddress:调度中心地址,天机学堂中就是填虚拟机地址
- appname:微服务名称
- ip和port:当前执行器的ip和端口,无需配置,自动获取
- accessToken:访问令牌,在调度中心中配置令牌,所有执行器访问时都必须携带该令牌,否则无法访问【修改虚拟机的/usr/local/src/xxl-job/application.properties文件中,修改xxl.job.accessToken属性,然后重启XXL-JOB即可】
- logPath:任务运行日志的保存目录
- logRetentionDays:日志最长保留时长

3.2.4 配置执行器和任务(页面)

  • 新建执行器【微服务名称和yml配置一致】

image-20240829172534332

  • 新建任务【JobHandler一定要和方法@XXlJob内容一致】

image-20240829173240249

3.2.5 创建方法–添加@XxlJob注解(微服务)

JobHandler一定要和方法@XXlJob内容一致

image-20240829173755449

3.2.6 启动测试(页面)

  • 启动本地微服务,会发现网页端执行器变化

image-20240829173441228

  • 启动任务

【想要测试的话也可以手动执行一次任务,但是要设置好调度策略】

image-20240829173930400

也可以在页面看到日志:

image-20240829174046001

4.XXL-Job任务分片[不同部署处理不同数据]

3.1 原理

刚才定义的定时持久化任务,通过while死循环,不停的查询数据,直到把所有数据都持久化为止。这样如果数据量达到数百万,交给一个任务执行器来处理会耗费非常多时间—->实例多个部署,这样就会有多个执行器并行执行(但是多个执行器执行相同代码,都从第一页开始也会重复处理)—->任务分片分片查询

举例[类似于发牌]:

image-20240830164322338

最终,每个执行器处理的数据页情况:

  • 执行器1:处理第1、4、7、10、13、…页数据
  • 执行器2:处理第2、5、8、11、14、…页数据
  • 执行器3:处理第3、6、9、12、15、…页数据

要想知道每一个执行器执行哪些页数据,只要弄清楚两个关键参数即可:

  • 起始页码(1,2,3):pageNo【执行器编号是多少,起始页码就是多少】
  • 下一页的跨度(步长3):step【执行器有几个,跨度就是多少。也就是说你要跳过别人读取过的页码,类似于分布式ID的步长】

因此,现在的关键就是获取两个数据:

  • 执行器编号
  • 执行器数量

这两个参数XXL-JOB作为任务调度中心,肯定是知道的,而且也提供了API帮助我们获取:

image-20240830164735039

这里的分片序号其实就是执行器序号,不过是从0开始,那我们只要对序号+1,就可以作为起始页码了

3.2 业务优化

根据实际情况,分成多个机器[这个用例,分片1,2,3;步长为1]

image-20240830164953405

3.3 引发问题解决方案

使用xxl-job定时每月初进行持久化:

①根据计算上个月时间创建上赛季mysql表

②根据查询出来上赛季redis数据,数据库新表名通过mp动态表名插件(本质是一个拦截器,在与mapper数据库接触过程中通过threadlocal更改数据库名)】然后查询数据
③根据非阻塞语句del删除redis上赛季数据—但是我考虑使用分片,这样导致分片1执行完异步执行删除,但是分片2执行完数据好像又回来了【针对②查询结果分页用xxlJob分片,log查日志没解决,我就打断点发现是分片次数问题,我就redis添加一个总数,一个分片执行次数,然后将删除逻辑放在一个新的定时任务,判断总数==分片执行次数,符合的情况才删除】

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 1.提出场景
  2. 2. 2.原理[统一管理]
  3. 3. 3.技术对比
  4. 4. ==———–XXL-Job———–==
  5. 5. 1.XXL-Job介绍
  6. 6. 2.XXL-Job部署[调度中心]
    1. 6.1. 2.1 创建数据库表
    2. 6.2. 2.2 Docker部署
  7. 7. 3.XXL-Job实战
    1. 7.1. 3.1 需求
    2. 7.2. 3.2 实现步骤
      1. 7.2.1. 3.2.1 引入xxl-job依赖(微服务)
      2. 7.2.2. 3.2.2 yml配置xxl-job(微服务)
      3. 7.2.3. 3.2.3 配置执行器类–XxlJobConfig(微服务)
      4. 7.2.4. 3.2.4 配置执行器和任务(页面)
      5. 7.2.5. 3.2.5 创建方法–添加@XxlJob注解(微服务)
    3. 7.3. 3.2.6 启动测试(页面)
  8. 8. 4.XXL-Job任务分片[不同部署处理不同数据]
    1. 8.1. 3.1 原理
    2. 8.2. 3.2 业务优化
    3. 8.3. 3.3 引发问题解决方案
,