定时任务框架Quartz的新玩法

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。作为企业级别的定时任务调度,Quartz不仅仅拥有强大的调度功能,也支持各种灵活的应用方式,并同时支持分布式和集群能力。 ## 基本使用 Quartz的使用非常简单,首先在POM里面加入引用 ```xml org.quartz-scheduler quartz

Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。作为企业级别的定时任务调度,Quartz不仅仅拥有强大的调度功能,也支持各种灵活的应用方式,并同时支持分布式和集群能力。

基本使用

Quartz的使用非常简单,首先在POM里面加入引用

<!-- Quartz -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.2.1</version>
</dependency>

然后在项目初始化的时候启动它

Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();

我们再定义一下定时任务要做啥

public class MyJob implements org.quartz.Job {

      public MyJob() {
      }

      public void execute(JobExecutionContext context) throws JobExecutionException {
          System.err.println("Hello World!  MyJob is executing.");
      }
  }

最后我们就可以增加一个定时任务了

 // 定义一个要执行的Job
  JobDetail job = newJob(MyJob.class)
      .withIdentity("job1", "group1")
      .build();
  // 定义一个间隔40秒运行的Trigger
  Trigger trigger = newTrigger()
      .withIdentity("trigger1", "group1")
      .startNow()
      .withSchedule(simpleSchedule()
              .withIntervalInSeconds(40)
              .repeatForever())
      .build();
  // 告诉Quartz去用trigger安排启动job
  scheduler.scheduleJob(job, trigger);

是不是很简单,其实还有很多用法可以直接取官网上看查阅一下文档,就可以快速实现你的功能了。
http://www.quartz-scheduler.org/documentation/quartz-2.2.x/quick-start.html

提高篇

Quartz在启动过程中会默认读取classpath下的quartz.preperties文件完成一些初始化工作。在这里我们主要谈的是org.quartz.jobStore.class这个配置项。

Quartz官方支持三种数据存储方式

  1. RAMJobStore

    RAMJobStore是默认的数据存储方式,其把数据存在本地内存中,官方宣称这是最有效率的方式(在本地内存当然快啦)。但是在宕机或者重启的时候数据就会丢失。
    //配置方式
    org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
  2. JDBCJobStore

    JDBCJobStore终于把数据给持久化起来了,这个也是使用最广泛的数据存储方式。在于Spring集成后都不需要自己再配置一遍数据库连接了。建表脚本在官方包里面可以找到(http://www.quartz-scheduler.org/downloads/)
    //配置方式
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
    org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    org.quartz.jobStore.tablePrefix = QRTZ_
    org.quartz.jobStore.dataSource = myDS
  3. TerracottaJobStore

    在Quartz被Software AG收购后免不了要夹带一些私货。这个就是专门给Terracotta配置的。我也就懒得讲了,大家网上搜搜吧。
    

说了这么多,其实都是Quartz的标准用法。在使用实践中因为各种原因导致没有办法使用官方提供的三种数据存储方式。所以只有自己动手丰衣足食,开辟新的玩法了。

进阶篇 --- MongoDB

在使用的时候我们会发现Quartz的建表脚本和公司idb不怎么兼容,尝试找过DBA,但是他们也不愿意为单独一个项目做特殊处理。这个时候我们就将视线投入到其他存储方式上了,首先祭出的就是MongoDB。

首先在POM里面引入第三方库

<dependency>
   <groupId>com.novemberain</groupId>
   <artifactId>quartz-mongodb</artifactId>
   <version>2.0.0</version>
</dependency>
<dependency>
   <groupId>org.mongodb</groupId>
   <artifactId>mongo-java-driver</artifactId>
   <version>3.2.2</version>
</dependency>

然后就和JDBCJobStore一样,在quartz.preperties中添加链接配置

org.quartz.jobStore.class=com.novemberain.quartz.mongodb.MongoDBJobStore
org.quartz.jobStore.mongoUri=${mongo.hostName}
org.quartz.jobStore.dbName=quartz
org.quartz.jobStore.collectionPrefix=mycol
org.quartz.threadPool.threadCount=1

如果要启动集群模式的话还需要加入下面的配置

org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.jobStore.isClustered = true

进阶篇 --- Redis

还有一种情况下你会发现没有MongoDB可以使用。环绕四周,还有Redis在旁边。看看内存刑的KV Strore,想想它也可以被持久化到磁盘,于是咬咬牙也就用上了。不过遗憾的是受限于Redis,Quartz不能全功能发挥出来。主要的限制有下面几点

  1. 只支持SimpleTrigger和CronTrigger
  2. 对GroupMatcher来说,只支持StringOperatorName.EQUALS操作
  3. org.quartz.scheduler.instanceName是不支持的,所以你得自己去维护trigger_group_name:trigger_name和job_group_name:job_name
  4. 没有办法使用transaction
  5. JobDataMap的内容是作为String存储和返回
  6. 定时任务没有优先级概念,只在设定的时间内启动

不过瑕不掩瑜(其实是我们也用不上这些高级功能),我们还是可以克服困难愉快的用上Quartz的。首先还是要引入三方包

<dependency>
   <groupId>net.joelinn</groupId>
   <artifactId>quartz-redis-jobstore</artifactId>
   <version>1.1.3</version>
</dependency>

<!-- Redis -->
<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>2.9.0</version>
</dependency>

其次还是配置一下quartz.preperties

org.quartz.jobStore.class = net.joelinn.quartz.jobstore.RedisJobStore
org.quartz.jobStore.host = ${redis.hostName}
org.quartz.jobStore.password = ${redis.password}
org.quartz.jobStore.port = ${redis.port}
org.quartz.jobStore.database: ${redis.database.quartz}

最后别忘了配置你的Jedis

   <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
       <property name="maxTotal" value="${redis.pool.maxTotal}"></property>
       <property name="maxIdle" value="${redis.pool.maxIdle}"></property>
       <property name="minIdle" value="${redis.pool.minIdle}"></property>
       <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"></property>
       <property name="minEvictableIdleTimeMillis" value="${redis.pool.minEvictableIdleTimeMillis}"></property>
       <property name="numTestsPerEvictionRun" value="${redis.pool.numTestsPerEvictionRun}"></property>
       <property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}"></property>
       <property name="testOnBorrow" value="true"></property>
       <property name="testOnReturn" value="true"></property>
       <property name="testWhileIdle" value="true"></property>
   </bean>

   <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
       <property name="hostName" value="${redis.hostName}"/>
       <property name="port" value="${redis.port}"/>
       <property name="timeout" value="${redis.timeout}"/>
       <property name="database" value="${redis.database.crowd}"/>
       <property name="password" value="${redis.password}"/>
       <property name="usePool" value="true"/>
       <property name="poolConfig" ref="jedisPoolConfig"/>
   </bean>

参考链接

  1. http://www.quartz-scheduler.org/
  2. https://github.com/michaelklishin/quartz-mongodb
  3. https://github.com/jlinn/quartz-redis-jobstore
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
目录
相关文章
|
JavaScript 前端开发
js 文字超出长度用省略号代替,鼠标悬停并以悬浮框显示
js 文字超出长度用省略号代替,鼠标悬停并以悬浮框显示
|
存储 对象存储
Ceph Reef(18.2.X)的对象存储网关(rgw)组件搭建
这篇文章是关于Ceph Reef(18.2.X)版本中对象存储系统的配置和使用案例,包括对象存储网关的概述、核心资源介绍、Ceph RGW支持的接口、高可用radosgw的部署、s3cmd工具的使用以及如何通过HTTP方式访问对象存储。
597 3
Ceph Reef(18.2.X)的对象存储网关(rgw)组件搭建
|
11月前
|
数据可视化 安全 数据挖掘
全面盘点:项目经理必备的产品管理工具!
在快节奏的商业环境中,产品管理工具如板栗看板、Jira、Smartsheet、Trello、Monday.com、Asana 和 Basecamp 等,对于提升团队效率和促进跨部门协作至关重要。这些工具各具特色,支持从项目跟踪到任务管理的各个方面,帮助团队顺利完成从概念到市场的产品开发过程。选择合适的工具时,应考虑功能匹配度、用户体验、成本效益、集成能力和安全性等因素。
|
10月前
|
Prometheus 监控 Cloud Native
在 Java 中,如何使用线程池监控以及动态调整线程池?
【10月更文挑战第22天】线程池的监控和动态调整是一项重要的任务,需要我们结合具体的应用场景和需求,选择合适的方法和策略,以确保线程池始终处于最优状态,提高系统的性能和稳定性。
1614 2
|
12月前
|
XML JavaScript Java
Spring Retry 教程
Spring Retry 是 Spring 提供的用于处理方法重试的库,通过 AOP 提供声明式重试机制,不侵入业务逻辑代码。主要步骤包括:添加依赖、启用重试机制、设置重试策略(如异常类型、重试次数、延迟策略等),并可定义重试失败后的回调方法。适用于因瞬时故障导致的操作失败场景。
237 1
Spring Retry 教程
|
存储 算法 机器人
路径规划的艺术:不同路径 II 的算法深掘【python力扣63题】
路径规划的艺术:不同路径 II 的算法深掘【python力扣63题】
|
JSON Java API
JSON & GSON - 读取 JSON 文件
JSON & GSON - 读取 JSON 文件
1319 0
|
存储 网络协议 安全
「译文」CMDB 最佳实践技术指南 -3-CMDB 应用映射 - 技术原理和最佳实践
「译文」CMDB 最佳实践技术指南 -3-CMDB 应用映射 - 技术原理和最佳实践
|
人工智能 Java 应用服务中间件
SpringBoot实战(十一):MultipartException: Could not parse multipart servlet request
SpringBoot实战(十一):MultipartException: Could not parse multipart servlet request
405 0
|
存储 开发框架 Java
分布式定时任务框架Quartz总结和实践(1)
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。
385 0