一次性入门三款分布式定时任务调度框架:Quartz、ElasticJob3.0、xxl-job

分布式定时任务调度框架(文末有源码)

  • 前言
  • 1、Quartz
    • 1.1 数据库
    • 1.2 maven依赖
    • 1.3 代码实现
      • 1.3.1 创建一个job
      • 1.3.1 为job设置trigger
    • 1.4 配置文件
    • 1.5 启动、测试
      • 1.1 单机
      • 1.2 集群
  • 2、ElasticJob
    • 2.1 下载zk
    • 2.2 新建三个类型的作业
    • 2.3 配置文件
    • 2.4 启动项目,测试数据
    • 2.5 分片作业(集群测试)
      • 2.5.1 **官方的三个分片策略:**
      • 2.5.2 启动三个实例,模拟集群
      • 2.5.3 模拟集群故障
    • 2.6 数据流作业
    • 2.7 控制台console
  • 3、xxl-job
    • 1.搭建调度中心(必须要搭)
      • 1.1 创建好数据库
      • 1.2 修改application.properties文件
      • 1.3 修改logback.xml文件
      • 1.4 启动项目
      • 1.5 打包部署
    • 2.springboot项目中集成
      • 2.1 maven依赖
      • 2.2 配置文件
      • 2.3 注入config
      • 2.4 新增job
      • 2.5 简单归纳一下
    • 3.结合控制台使用
      • 3.1 配置执行管理器
      • 3.2 新增一个任务
      • 3.3 启动
    • 4.用分片任务,来验证xxl-job的集群功能
      • 4.1 修改端口
      • 4.2 新建执行器
      • 4.3 新建任务代码+任务
      • 4.4 运行一次验证
    • 5.对Quartz的优化
  • 4、结语
  • 5、附录1
  • 6、附录2

前言

本来是打算水三篇文章的,但是最后想想还是打包一起,这样后来自己看也方便一点,所以本文略长,大家可以按需目录跳转阅读。每个框架都包含了入门的代码示例,文末会贴上源码链接,大家可以下载阅读。

本文主要是为了示例,包含了 单机和集群 的代码,一些基本的概念知识就不说了,大家可以去官网详细阅读。

1、Quartz

最经典的一款框架,下面两个框架都是基于Quartz改进的。本文版本用的最新版本:2.3.0
核心理念

  • scheduler:调度器
  • job:任务本身
  • trigger:触发器

1.1 数据库

Quartz是基于数据库来做任务调度的,所以我们要先把数据库构造好,用官网给的SQL脚本。
由于脚本太长了,放在这里占位置影响阅读,附录1有完整脚本,直接copy
如果大家有源码的,在src\org\quartz\impl\jdbcjobstore这个目录下面,也可以解压maven依赖,一样可以获取到SQL脚本

创建好的就这么11张表
在这里插入图片描述

1.2 maven依赖

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.10.0</version></dependency>

我这里引入c3p0是因为会报连接错误,但是网上其他文章不用引入这个依赖,我猜测可能是版本不一样,然后某个Maven依赖冲突导致的。

1.3 代码实现

创建job的方式有两种,一种是比较古老的,用scheduler去绑定job和config,由于配置复杂,不是很推荐,推荐用spring bean的自动装配。

1.3.1 创建一个job

@DisallowConcurrentExecution注解是关键,用于集群中单个job只能被一个实例机器执行。

//禁止并发执行
@DisallowConcurrentExecution
//更新JobDataMap 副本
@PersistJobDataAfterExecution
public class ZedJob extends QuartzJobBean {private static final Logger logger = LoggerFactory.getLogger(ZedJob.class);@Overrideprotected void executeInternal(JobExecutionContext context) throws JobExecutionException {logger.info("我是ZedJob");}
}

1.3.1 为job设置trigger

@Configuration
public class QuartzConfig {@Beanpublic JobDetail jobDetail(){return JobBuilder.newJob(ZedJob.class)// 指定任务的名称.withIdentity("zedJob")// 任务描述.withDescription("任务描述:这是一个任务")// 每次任务执行后进行存储.storeDurably().build();}@Beanpublic Trigger trigger() {//创建触发器SimpleScheduleBuilder simpleScheduleBuilder1 = SimpleScheduleBuilder.repeatSecondlyForever(5);return TriggerBuilder.newTrigger()// 绑定工作任务.withIdentity("zedJob").forJob(jobDetail())// 每隔 5 秒执行一次 job.withSchedule(simpleScheduleBuilder1).build();}
}

这里的Schedule常用的有两种,一个是SimpleScheduleBuilder,一个是CronScheduleBuilder,写cron表达式的,大家可以按照需要选取。

1.4 配置文件

上面基本都有注释

spring:quartz:#存储方式,默认是内存memoryjob-store: jdbc#应用关闭时,是否等待定时任务执行完成wait-for-jobs-to-complete-on-shutdown: trueproperties:org:quartz:scheduler:#相同 Scheduler 名字的节点,形成一个 Quartz 集群instanceName: SC_SchedulerinstanceId: AUTOjobStore:class: org.quartz.impl.jdbcjobstore.JobStoreTX
#            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegatedataSource: quartz_jobs#是否集群部署isClustered: true# 集群检查周期,单位为毫秒,可以自定义缩短时间。当某一个节点宕机的时候,其他节点等待多久后开始执行任务clusterCheckinInterval: 5000threadPool:threadCount: 25 # 线程池大小。默认为 10 。threadPriority: 5 # 线程优先级class: org.quartz.simpl.SimpleThreadPool # 线程池类型dataSource:#这个名字是上面的jobStore.dataSource定义的quartz_jobs:driver: com.mysql.cj.jdbc.DriverURL: jdbc:mysql://172.16.72.134:3306/quartz_jobs?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8&useUnicode=trueuser: rootpassword: 123456

我这里挑几个比较重要的来说一下:

  • job-store:指定存储方式,如果要部署分布式集群,必须要选择jdbc
  • instanceName:同一个集群,instanceName要一样,quartz在数据库中是用名字来区分是否是一个集群的。
  • isClustered:这是集群的开启开关
  • dataSource:选择数据库集群后,才会有这个配置
  • quartz_jobs:命名记得一致

1.5 启动、测试

1.1 单机

启动单个服务,看看打印,都是正常的。
在这里插入图片描述

1.2 集群

只修改端口,启动两个实例,测试@DisallowConcurrentExecution 并发执行,记得数据库这些配置信息要一致
可以看到,我们第二个实例中,没有任何打印
在这里插入图片描述
我们关闭第一个实例,假装宕机,看看第二个实例能否正常接续工作
在这里插入图片描述
当关闭1后,我们可以看到,示例2中检测到了1的关闭,并且有打印三句话,这三句话的意思翻译一下:

  1. 检测到集群中有一个实例失去连接或者在重启
  2. 扫描是否有其他示例可以接待挂掉的那个主机继续执行任务
  3. 找到了1个实例,去继续执行

所以由此也可以看出quartz集群的能力和容错能力。

2、ElasticJob

ElasticJob把任务命名为作业,等同于任务,job,叫法不同而已,所以下面都用作业来说

2.1 下载zk

  1. 去官网下载最新版本:下载链接

  2. 解压,进入conf 路径下,将文件 zoo_sample.cfg 修改为 zoo.cfg

    mv zoo_sample.cfg zoo.cfg
    
  3. 在zk根目录下创建目录zkData

    mkdir zkData
    
  4. 打开 zoo.cfg 文件,修改 dataDir 路径为新创建的zkData路径

    dataDir=/usr/local/zookeeper/apache-zookeeper-3.9.2-bin/zkData
    
  5. 进入bin目录,启动zk

    ./zkServer.sh start
    
  6. 运行客户端,创建命名空间

    ./zkCli.sh
    
    create /elastic-job-test
    

2.2 新建三个类型的作业

ZedJob:普通的作业
FragmentationJob:分片作业
FlowJob:数据流作业

@Component
public class ZedJob implements SimpleJob {private static final Logger logger = LoggerFactory.getLogger(ZedJob.class);@Overridepublic void execute(ShardingContext shardingContext) {logger.info("我是影流之主 Zed");}
}
@Component
public class FragmentationJob implements SimpleJob {private static final Logger logger = LoggerFactory.getLogger(FragmentationJob.class);@Overridepublic void execute(ShardingContext shardingContext) {logger.info("分片任务");switch (shardingContext.getShardingItem()) {case 0:logger.info("分片0:{}",shardingContext.getShardingParameter());break;case 1:logger.info("分片1:{}",shardingContext.getShardingParameter());break;case 2:logger.info("分片2:{}",shardingContext.getShardingParameter());break;default:break;}}
}
@Component
public class FlowJob implements DataflowJob<UserInfo> {private static final Logger logger = LoggerFactory.getLogger(FlowJob.class);@Overridepublic List<UserInfo> fetchData(ShardingContext shardingContext) {List<UserInfo> foos = new ArrayList<>();double random = Math.random();if (random > 0.5) {logger.info("fetchData------ {}", random);UserInfo foo = new UserInfo();foo.setUserName("小道仙");foos.add(foo);}return foos;}@Overridepublic void processData(ShardingContext shardingContext, List<UserInfo> list) {logger.info("收到流数据");list.forEach(i -> logger.info("name为:{}", i.getUserName()));}
}

2.3 配置文件

大多都有注释,大家看看就行,其中shardingTotalCount必填,等待重试的间隔也很重要。

elasticjob:regCenter:#zookeeper 的ip:portserverLists: 172.16.72.133:2181#名命空间,和前面zk里面创建的一样就行namespace: elastic-job-testbase-sleep-time-milliseconds: 10000# 等待重试的间隔时间的最大值,这个很重要,不然项目启动会出现timeout的报错max-sleep-time-milliseconds: 30000jobs:#我们创建的三个任务,在这里进行配置zedJob:#定时任务的全路径名elasticJobClass: com.wq.elasticjob.ZedJob#定时任务执行的cron表达式cron: 0/5 * * * * ?#分片数量shardingTotalCount: 1fragmentationJob:#定时任务的全路径名elasticJobClass: com.wq.elasticjob.FragmentationJob#定时任务执行的cron表达式cron: 0/10 * * * * ?#分片数量shardingTotalCount: 3#这是分片参数,代码中获取,记得加引号,不然获取不到shardingItemParameters: "0=text,1=image,2=video"flowJob:#定时任务的全路径名elasticJobClass: com.wq.elasticjob.FlowJob#定时任务执行的cron表达式cron: 0/10 * * * * ?#分片数量shardingTotalCount: 1

2.4 启动项目,测试数据

我们先看看普通的作业,这个没可说的,看看能否正常运行就好
在这里插入图片描述
接下来重点说说分片任务,以及流数据任务。

2.5 分片作业(集群测试)

2.5.1 官方的三个分片策略:

AverageAllocationJobShardingStrategy:根据分片项平均分片
如果分片不能整除,则不能整除的多余分片将依次追加到序号小的服务器。策略举例:
假设有3台服务器,
分成9片,则每台服务器分到的分片是:1【0,1,2】,2【3,4,5】,3【6,7,8】
分成8片,则每台服务器分到的分片是:1【0,1,6】,2【2,3,7】,3【4,5】
分成10片,则每台服务器分到的分片是:1【0,1,2】,2【3,4,5】,3【6,7,8】

OdevitySortByNameJobShardingStrategy:根据作业名称哈希值的奇偶数决定按照作业服务器 IP 升序或是降序的方式分片
缺点是,一旦分片数小于作业服务器数,作业将永远分配至IP地址靠前的服务器,导致IP地址靠后的服务器空闲

RotateServerByNameJobShardingStrategy:根据作业名称轮询分片
假设有3台服务器,顺序为 【0, 1, 2】,如果作业名的哈希值根据作业分片总数取模为 1, 作业节点顺序变为 【1, 2, 0】。

2.5.2 启动三个实例,模拟集群

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回顾一下,我们分片任务的配置:shardingItemParameters: “0=text,1=image,2=video”,总数有三个,启动三个实例,刚好一个机器一个,而且参数也能打印出来,而且分片策略,默认采用的是平均分片。

2.5.3 模拟集群故障

现在我把三个集群中index为0的干掉,看看效果。
在这里插入图片描述
在这里插入图片描述
通过打印可以看到,本来三个集群一人一个,现在挂掉了一个,其中一个服务还是一个,另一个服务则是拥有了两个分片,到这里也就验证结束

2.6 数据流作业

回到我们流数据任务的代码:

    @Overridepublic List<UserInfo> fetchData(ShardingContext shardingContext) {List<UserInfo> foos = new ArrayList<>();double random = Math.random();if (random > 0.5) {logger.info("fetchData------ {}", random);UserInfo foo = new UserInfo();foo.setUserName("小道仙");foos.add(foo);}return foos;}@Overridepublic void processData(ShardingContext shardingContext, List<UserInfo> list) {logger.info("收到流数据");list.forEach(i -> logger.info("name为:{}", i.getUserName()));}

我们实现的DataflowJob接口,覆盖了两个方法,一个fetchData,一个processData

  • fetchData:对数据作处理
  • processData:如果fetchData方法中产生了数据(数据发生了改变),则会携带者数据进入这个方法

我们看看日志打印,当我们在fetchData中设置了userName后,就会进入processData方法,就会拿到我们设置的userName属性
在这里插入图片描述

2.7 控制台console

  1. 选择对应版本下载
    控制台官网下载:https://www.apache.org/dyn/closer.cgi/shardingsphere/elasticjob-ui-3.0.0-RC1/apache-shardingsphere-elasticjob-3.0.0-RC1-lite-ui-bin.tar.gz
  2. 解压后进入bin目录,选择start.bat双击启动
  3. 网页访问localhost:8088/,用户名/密码:root/root
  4. 按照下图三个步骤配置zk注册中心,然后就能使用了
    在这里插入图片描述

3、xxl-job

截止本文编写时候,xxl的最新Maven版本为2.4.1,所以我们就用最新的

我们把xxl-job看做两部分,一部分是搭建调度中心,一部分是代码中实现集成

1.搭建调度中心(必须要搭)

下载源码,仓库地址:
gitee地址:https://gitee.com/xuxueli0323/xxl-job/blob/master/doc/db/tables_xxl_job.sql
GitHub地址:https://github.com/xuxueli/xxl-job

1.1 创建好数据库

脚本在这个目录下面:doc/db/tables_xxl_job.sql

调度中心支持集群部署,集群情况下各节点务必连接同一个mysql实例;
如果mysql做主从,调度中心集群节点务必强制走主库;

这里给出所有数据库的作用:

  • xxl_job_lock:任务调度锁表;
  • xxl_job_group:执行器信息表,维护任务执行器信息;
  • xxl_job_info:调度扩展信息表: 用于保存XXL-JOB调度任务的扩展信息,如任务分组、任务名、机器地址、执行器、执行入参和报警邮件等等;
  • xxl_job_log:调度日志表: 用于保存XXL-JOB任务调度的历史信息,如调度结果、执行结果、调度入参、调度机器和执行器等等;
  • xxl_job_log_report:调度日志报表:用户存储XXL-JOB任务调度日志的报表,调度中心报表功能页面会用到;
  • xxl_job_logglue:任务GLUE日志:用于保存GLUE更新历史,用于支持GLUE的版本回溯功能;
  • xxl_job_registry:执行器注册表,维护在线的执行器和调度中心机器地址信息;
  • xxl_job_user:系统用户表;

不想去找的直接文末附录二有完整的SQL脚本,直接copy

1.2 修改application.properties文件

修改server.port为自己需要的
修改spring.datasource.url,数据库配置为自己的
修改spring.mail.username和from为自己的实际邮箱地址(不修改也可以,这个就是通知用的)

1.3 修改logback.xml文件

将name=“log.path” 这个路径修改为自己的路径,并且在路径下创建xxl-job-admin.log文件,如果你不修改用默认的也行。

1.4 启动项目

浏览器访问:localhost:8088/xxl-job-admin/,默认用户名密码为admin,123456
出现下面这个界面则搭建成功
在这里插入图片描述

1.5 打包部署

生产环境下,配置好以后,打包部署到服务器即可

2.springboot项目中集成

2.1 maven依赖

<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.4.1</version>
</dependency>

2.2 配置文件

xxl:job:admin:#如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册addresses: http://127.0.0.1:8088/xxl-job-adminexecutor:appname: zed-demologpath:logretentiondays: 30#执行器IP:默认为空表示自动获取IPip: 127.0.0.1#默认为9999port: 9999#优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址address:#执行器通讯TOKEN [选填]:非空时启用; 要和调度中心服务部署配置的accessToken一致accessToken: default_token

2.3 注入config

这个config是官方源码,内容一样,但是必须要copy进我们自己的项目里

@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;@Beanpublic 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>*             <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.4 新增job

这里用最常用最推荐的一种写法,就是将任务绑定在方法上,@XxlJob注解标明每一个任务。当然还有绑定在Bean上的,不过这样就会写很多Bean,用方法的话,一个类就够了。

@Component
public class XxlJobFactory {private static Logger logger = LoggerFactory.getLogger(XxlJobFactory.class);@XxlJob("zedJobTest")public void zedJobTest(){logger.info("这是zedJobTest");}
}

2.5 简单归纳一下

我们在springBoot项目集成的时候,有几个比较关键的点,我在这里给大家总结一下,免得绕进去。

  1. 第一步搭建的调度中心,你可以理解为es job 的zookeeper一样,或者nacos这样的角色,它是一个注册中心,是整个框架的驱动核心,采用db的方式来进行服务的注册。
  2. xxl.job.admin:这个在springboot中的配置,就是配置第一步的调度中心的,地址前面一定要加http
  3. xxl.job.executor:这个是接下来要说的执行管理器,去执行任务的executor,它配置在我们的网页控制台中。这个的ip和端口是单独分开的,专门控制executor
  4. 很多配置都是空的,因为都有默认的,但是我们在注入XxlJobConfig的时候必须要用,所以空着就空着

3.结合控制台使用

3.1 配置执行管理器

新增一个执行管理器,这就是我们前面说到的,xxl.job.executor配置所控制的东西,它有一个默认的,我们不用默认的用自己的。
在这里插入图片描述
在这里插入图片描述
这个appName一定要和xxl.job.executor里面的appname一样,一般默认自动注册就好,如果自动注册不行,就手动录入,输入我们的ip和端口,这个ip和端口,也一定要和xxl.job.executor.port一致

3.2 新增一个任务

在这里插入图片描述
这里面最主要注意三个点,就是我标出来的这三个
在这里插入图片描述

  1. 执行器选择我们第二步中创建的执行器
  2. 运行模式常用Bean
  3. 然后jobHander要和代码中,注解@XxlJob中的Value一致

其他的根据自己需求改写就行

3.3 启动

在这里插入图片描述
这里选择执行一次,忽略corn表达式,只执行一次,选择下面的启动,才会走corn表达式逻辑。

执行一次这里,可以加任务参数和重新指定机器地址,由于我们执行器里面配置好了的,所以不用填写让它自动获取。
在这里插入图片描述

看看控制台打印,任务是调动成功了的。
在这里插入图片描述
然后数据库里,也可以看到我们新增的任务,还有其他表的信息
在这里插入图片描述

4.用分片任务,来验证xxl-job的集群功能

4.1 修改端口

修改springboot的端口和executor的port,启动三个实例

4.2 新建执行器

新建一个执行器fragmentatio
在这里插入图片描述
这里自动注册如果获取不到,我们就手动录入,三个不同的端口之间用逗号分隔。外面查看也是正确的。
在这里插入图片描述

4.3 新建任务代码+任务

    /*** 2、分片广播任务*/@XxlJob("shardingJobHandler")public void shardingJobHandler(String param) throws Exception {int shardTotal = XxlJobHelper.getShardTotal();int index = XxlJobHelper.getShardIndex();logger.info("总共:{}个分片,当前的index为:{}", shardTotal, index);}

记得路由策略选择分片广播
在这里插入图片描述

4.4 运行一次验证

我们看看控制台打印,我这里贴一个就行了,三个实例,总共3个分片,index为0,1,2,大家可以根据分片总数和index,自己去实现分片处理逻辑,比如取模。
在这里插入图片描述

5.对Quartz的优化

xxl-job,是徐雪里基于Quartz改进来的,Quartz有下面几点不足:

  1. 调用API的的方式操作任务,不人性化;
  2. 需要持久化业务QuartzJobBean到底层数据表中,系统侵入性相当严重。
  3. 调度逻辑和QuartzJobBean耦合在同一个项目中,这将导致一个问题,在调度任务数量逐渐增多,同时调度任务逻辑逐渐加重的情况下,此时调度系统的性能将大大受限于业务;
  4. quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务,会导致节点负载悬殊非常大;而XXL-JOB通过执行器实现“协同分配式”运行任务,充分发挥集群优势,负载各节点均衡。

XXL-JOB弥补了quartz的上述不足之处

4、结语

都看到这里了,给我点个赞和关注不过分吧,如果你只是使用分布式任务调度框架,本文的示例绝对够用,如果你们项目很庞大而且很复杂,那么还要去官网查看更详细的配置。

本文完整项目代码GitHub地址
https:https://github.com/wangqing-github/DubboAndNacos.git
ssh:git@github.com:wangqing-github/DubboAndNacos.git
有三个分支,代码都是独立的,大家可以从主干切换。
在这里插入图片描述

5、附录1

Quartz的数据库SQL脚本:

#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;CREATE TABLE QRTZ_JOB_DETAILS(SCHED_NAME VARCHAR(120) NOT NULL,JOB_NAME  VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,JOB_CLASS_NAME   VARCHAR(250) NOT NULL,IS_DURABLE VARCHAR(1) NOT NULL,IS_NONCONCURRENT VARCHAR(1) NOT NULL,IS_UPDATE_DATA VARCHAR(1) NOT NULL,REQUESTS_RECOVERY VARCHAR(1) NOT NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);CREATE TABLE QRTZ_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,JOB_NAME  VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,NEXT_FIRE_TIME BIGINT(13) NULL,PREV_FIRE_TIME BIGINT(13) NULL,PRIORITY INTEGER NULL,TRIGGER_STATE VARCHAR(16) NOT NULL,TRIGGER_TYPE VARCHAR(8) NOT NULL,START_TIME BIGINT(13) NOT NULL,END_TIME BIGINT(13) NULL,CALENDAR_NAME VARCHAR(200) NULL,MISFIRE_INSTR SMALLINT(2) NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);CREATE TABLE QRTZ_SIMPLE_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,REPEAT_COUNT BIGINT(7) NOT NULL,REPEAT_INTERVAL BIGINT(12) NOT NULL,TIMES_TRIGGERED BIGINT(10) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_CRON_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,CRON_EXPRESSION VARCHAR(200) NOT NULL,TIME_ZONE_ID VARCHAR(80),PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_SIMPROP_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,STR_PROP_1 VARCHAR(512) NULL,STR_PROP_2 VARCHAR(512) NULL,STR_PROP_3 VARCHAR(512) NULL,INT_PROP_1 INT NULL,INT_PROP_2 INT NULL,LONG_PROP_1 BIGINT NULL,LONG_PROP_2 BIGINT NULL,DEC_PROP_1 NUMERIC(13,4) NULL,DEC_PROP_2 NUMERIC(13,4) NULL,BOOL_PROP_1 VARCHAR(1) NULL,BOOL_PROP_2 VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_BLOB_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,BLOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_CALENDARS(SCHED_NAME VARCHAR(120) NOT NULL,CALENDAR_NAME  VARCHAR(200) NOT NULL,CALENDAR BLOB NOT NULL,PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_GROUP  VARCHAR(200) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_FIRED_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,ENTRY_ID VARCHAR(95) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,FIRED_TIME BIGINT(13) NOT NULL,SCHED_TIME BIGINT(13) NOT NULL,PRIORITY INTEGER NOT NULL,STATE VARCHAR(16) NOT NULL,JOB_NAME VARCHAR(200) NULL,JOB_GROUP VARCHAR(200) NULL,IS_NONCONCURRENT VARCHAR(1) NULL,REQUESTS_RECOVERY VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);CREATE TABLE QRTZ_SCHEDULER_STATE(SCHED_NAME VARCHAR(120) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,LAST_CHECKIN_TIME BIGINT(13) NOT NULL,CHECKIN_INTERVAL BIGINT(13) NOT NULL,PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);CREATE TABLE QRTZ_LOCKS(SCHED_NAME VARCHAR(120) NOT NULL,LOCK_NAME  VARCHAR(40) NOT NULL,PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);commit;

6、附录2

xxl的sql脚本

CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
use `xxl_job`;SET NAMES utf8mb4;CREATE TABLE `xxl_job_info` (`id` int(11) NOT NULL AUTO_INCREMENT,`job_group` int(11) NOT NULL COMMENT '执行器主键ID',`job_desc` varchar(255) NOT NULL,`add_time` datetime DEFAULT NULL,`update_time` datetime DEFAULT NULL,`author` varchar(64) DEFAULT NULL COMMENT '作者',`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',`schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',`schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',`misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',`glue_source` mediumtext COMMENT 'GLUE源代码',`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',`trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行',`trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',`trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`job_group` int(11) NOT NULL COMMENT '执行器主键ID',`job_id` int(11) NOT NULL COMMENT '任务,主键ID',`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',`trigger_code` int(11) NOT NULL COMMENT '调度-结果',`trigger_msg` text COMMENT '调度-日志',`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',`handle_code` int(11) NOT NULL COMMENT '执行-状态',`handle_msg` text COMMENT '执行-日志',`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',PRIMARY KEY (`id`),KEY `I_trigger_time` (`trigger_time`),KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_log_report` (`id` int(11) NOT NULL AUTO_INCREMENT,`trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',`running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',`suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',`fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_logglue` (`id` int(11) NOT NULL AUTO_INCREMENT,`job_id` int(11) NOT NULL COMMENT '任务,主键ID',`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',`glue_source` mediumtext COMMENT 'GLUE源代码',`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',`add_time` datetime DEFAULT NULL,`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_registry` (`id` int(11) NOT NULL AUTO_INCREMENT,`registry_group` varchar(50) NOT NULL,`registry_key` varchar(255) NOT NULL,`registry_value` varchar(255) NOT NULL,`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`),KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_group` (`id` int(11) NOT NULL AUTO_INCREMENT,`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',`title` varchar(12) NOT NULL COMMENT '执行器名称',`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(50) NOT NULL COMMENT '账号',`password` varchar(50) NOT NULL COMMENT '密码',`role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',`permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',PRIMARY KEY (`id`),UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_lock` (`lock_name` varchar(50) NOT NULL COMMENT '锁名称',PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');commit;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/882345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nature?拿捏~

之前有分享过很多《Nature》论文插图&#xff0c;想着为大家提供更加广阔的作图思路。 但有人说&#xff0c;这些图好看是好看&#xff0c;可惜也就大佬们能画&#xff0c;跟我这个小卡拉米没啥关系。 此言差矣。 如果我说&#xff0c;Matlab就能画呢&#xff1f; 比如&…

AIGC助力小学生编程梦:C++入门不再难!

文章目录 一、AIGC时代下的编程教育新趋势二、小学生C入门趣味编程的意义三、小学生C入门趣味编程的实践策略四、面临的挑战与应对策略五、AIGC技术在小学生C编程中的应用与前景《小学生C趣味编程从入门到精通》编辑推荐内容简介作者简介目录 随着人工智能生成内容&#xff08;…

C++初阶——入门

目录 1、C发展历史 2、C版本更新 3、C参考文档 4、C书籍推荐 5、C的程序 6、命名空间 6.1 namespace的作用 6.2 namespace的定义 6.3 namespace的使用 7、C输入&输出 8、缺省参数 9、函数重载 10、引用 10.1 引用的概念和定义 10.2 引用的特性 10.3 引用的使…

10月9日

肯定是对x求导 刨根问底求导数解析式 区间再现均值不等式 没利用B-E 0 同解方程组 趋于0的时候&#xff0c;看1次项 没有考虑x -1的情况 还要加一&#xff0c;非齐次解

AdaTAD(CVPR 2024)视频动作检测方法详解

前言 论文&#xff1a;End-to-End Temporal Action Detection with 1B Parameters Across 1000 Frames 代码&#xff1a;AdaTAD 从论文标题可以看出&#xff0c;AdaTAD 可以在 1B 参数且输入视频在 1000 帧的情况下实现端到端的训练&#xff0c;核心创新点是引入 Temporal-Inf…

STM32_实验4_控制蜂鸣器

1.设置 PB2 引脚&#xff0c;生成代码。 2.打开蜂鸣器 // 循环反复HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); // 开启蜂鸣器printf("beep on\n");HAL_Delay(500); // 等待响500msHAL_GPIO_WritePin(…

解锁C++多态的魔力:灵活与高效的编码艺术(下)

文章目录 前言&#x1f3b1;四、多态的原理&#x1f52e;4.1 虚函数表&#xff08;vtable&#xff09;&#x1f52e;4.2 派生类对象中的虚函数表4.2.1 编写程序去访问虚函数表4.2.2 虚表存储位置的验证 &#x1f3b1;五、 多态的静态绑定和动态绑定&#x1f52e;5.1 静态绑定&a…

spring底层原理

本文参考黑马程序员的spring底层讲解&#xff0c;想要更详细的可以去看视频。 另外文章会每日更新&#xff0c;大概持续1个月&#xff01;&#xff01;&#xff01;每天更新一讲 这部分比较抽象&#xff0c;要经常复习&#xff01;&#xff01;&#xff01; 一、BeanFactory与A…

【JPCS独立出版 | 福州大学主办 | 有确定的ISSN号】第三届可再生能源与电气科技国际学术会议(ICREET 2024)

第三届可再生能源与电气科技国际学术会议&#xff08;ICREET 2024&#xff09; 2024 3rd International Conference on Renewable Energy and Electrical Technology ICREET 2024已成功申请JPCS - Journal of Physics: Conference Series (ISSN:1742-6596) 独立出版&#xf…

引领智慧文旅新纪元,开启未来旅游新境界

融合创新科技&#xff0c;重塑旅游体验&#xff0c;智慧文旅项目定义旅游新未来 在全球化的浪潮中&#xff0c;旅游已成为连接世界的重要纽带。智慧文旅项目&#xff0c;不仅仅是一次技术的革新&#xff0c;更是对旅游行业未来发展的一次深刻思考。信鸥科技通过运用云计算、大数…

Vue3动态组件原来是这样

什么是Vue3动态组件 在Vue3中&#xff0c;动态组件简单来说就是根据不同的条件进行不同组件的渲染&#xff0c;可以联想一下在前端中常用到的动态样式 基本使用 在Vue3中&#xff0c;动态组件的使用也是非常简单的&#xff0c;只需要使用<component>标签&#xff0c;并…

WPFDeveloper正式版发布

WPFDeveloper WPFDeveloper一个基于WPF自定义高级控件的WPF开发人员UI库&#xff0c;它提供了众多的自定义控件。 该项目的创建者和主要维护者是现役微软MVP 闫驚鏵: https://github.com/yanjinhuagood 该项目还有众多的维护者&#xff0c;详情可以访问github上的README&…

Redis 高可用:从主从到集群的全面解析

目录 一、主从复制 (基础)1. 同步复制a. 全量数据同步b. 增量数据同步c. 可能带来的数据不一致 2. 环形缓冲区a. 动态调整槽位 3. runid4. 主从复制解决单点故障a. 单点故障b. 可用性问题 5. 注意事项a. Replica 主动向 Master 建立连接b. Replica 主动向 Master 拉取数据 二、…

STM32传感器模块编程实践(八) HX711压力传感器称重模块简介及驱动源码

文章目录 一.概要二.HX711主要技术指标三.HX711模块参考原理图四.模块接线说明五.模块工作原理介绍六.模块通讯协议介绍七.STM32单片机与HX711模块实现重量测量实验1.硬件准备2.软件工程3.软件主要代码4.实验效果 八.小结 一.概要 电子秤是将检测与转换技术、计算机技术、信息…

Python网络爬虫从入门到实战

目录 引言 一、网络爬虫的概念 二、 网络爬虫的基本工作流程 &#xff08;一&#xff09;过程&#xff1a; &#xff08;二&#xff09;安装requests模块和beautifulsoup4模块 &#xff08;三&#xff09;requests库的使用 1、requests库的基本介绍 2、导入requests库的…

一款零依赖、跨平台的流媒体协议处理工具,支持 RTSP、WebRTC、RTMP 等视频流协议的处理

大家好&#xff0c;今天给大家分享一款功能强大的流媒体协议处理工具go2rtc&#xff0c;支持多种协议和操作系统&#xff0c;具有零依赖、零配置、低延迟等特点。 项目介绍 go2rtc可以从各种来源获取流&#xff0c;包括 RTSP、WebRTC、HomeKit、FFmpeg、RTMP 等&#xff0c;并…

学习文档10/16

MySQL 字符集&#xff1a; MySQL 支持很多种字符集的方式&#xff0c;比如 GB2312、GBK、BIG5、多种 Unicode 字符集&#xff08;UTF-8 编码、UTF-16 编码、UCS-2 编码、UTF-32 编码等等&#xff09;。 查看支持的字符集 你可以通过 SHOW CHARSET 命令来查看&#xff0c;支持…

ARINC 429总线协议

一、概述 ARINC 是美国航空无线电公司英文字头的缩写&#xff0c; 该公司1977年7月21日出版了“ARINC 429规范”一书&#xff0c;429规范就是飞机电子系统之间数字式数据传输的标准格式&#xff0c;在飞机上使用429总线的电子设备均应遵守这个规范&#xff0c;这样才能保证电子…

Redis应用高频面试题

Redis 作为一个高性能的分布式缓存系统,广泛应用于后端开发中,因此在后端研发面试中,关于 Redis 的问题十分常见。 本文整理了30个常见的 Redis 面试题目,涵盖了 Redis 的源码、数据结构、原理、集群模式等方面的知识,并附上简要的回答,帮助大家更好地准备相关的面试。 …

2024年【N2观光车和观光列车司机】及N2观光车和观光列车司机模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 N2观光车和观光列车司机考前必练&#xff01;安全生产模拟考试一点通每个月更新N2观光车和观光列车司机模拟考试题题目及答案&#xff01;多做几遍&#xff0c;其实通过N2观光车和观光列车司机操作证考试很简单。 1、…