使用場景:
1.如果使用內存保存定時信息,一旦服務器宕機,那麼定時信息全部丟失,定時任務無法恢復,而使用數據庫保存定時任務信息,能夠在服務器重啓後,恢復原來定時任務的狀態,繼續執行。
2.在集羣環境下,多個服務器同時啓動定時任務,會出現任務的多次重複執行,這就需要集羣環境下,某一時刻只有一臺服務器執行定時任務,當主服務器宕機後,從服務器能夠接力執行定時任務。
quartz的數據庫方案,可以很好的滿足上面的兩種情景。
SQL
文件下載
表結構創建語句可以在quartz官網下載
下載完成之後解壓,在docs\dbTables
目錄下有各種版本的sql
文件,這裏我用的是tables_mysql_innodb.sql
適用於mysql
的innodb
版本
表結構說明
調度器:存儲少量有關調度器的狀態信息。
存儲各種觸發器,觸發器觸發的記錄,觸發器組的暫停信息。
序號 | 表名 | 說明 |
---|---|---|
1. | qrtz_job_details |
存儲每一個已配置的 Job 的詳細信息(jobDetail ) |
2. | qrtz_triggers |
存儲已配置的 觸發器 (Trigger) 的信息 |
3. | qrtz_fired_triggers |
存儲與已觸發的 Trigger 相關的狀態信息,以及相聯 Job 的執行信息 |
4. | qrtz_cron_triggers |
存儲 Cron Trigger ,包括 Cron 表達式和時區信息 |
5. | qrtz_simple_triggers |
存儲簡單的 Trigger,包括重複次數,間隔,以及已觸的次數 |
6. | qrtz_blog_triggers |
以 Blob 類型存儲的Trigger |
7. | qrtz_scheduler_state |
調度器狀態。 |
8. | qrtz_locks |
存儲程序的悲觀鎖的信息(假如使用了悲觀鎖)。 |
9. | qrtz_calendars |
以 Blob 類型存儲 Quartz 的 Calendar 信息 |
注意:cron
方式需要用到的4張數據表: qrtz_triggers
,qrtz_cron_triggers
,qrtz_fired_triggers
,qrtz_job_details
。
配置文件
#==============================================================
#配置調度器配置
#==============================================================
#在同一個程序中,使用該名稱來區分scheduler,如果是集羣環境,必須使用同一個名稱,表示邏輯相同的Scheduler
org.quartz.scheduler.instanceName = MyScheduler
#在集羣環境下,instanceId必須唯一,即使是邏輯相同的Scheduler,一般設爲AUTO
org.quartz.scheduler.instanceId = AUTO
#==============================================================
#線程池配置,
#==============================================================
#必須配置,線程池實現的類名,Quartz附帶的線程池是“org.quartz.simpl.SimpleThreadPool”,並且應該能夠滿足幾乎每個用戶的需求。它有非常簡單的行爲,並經過很好的測試。它提供了一個固定大小的線程池,
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#必須配置,線程數
org.quartz.threadPool.threadCount = 10
#線程優先級,默認是5
org.quartz.threadPool.threadPriority = 5
#==============================================================
#JobStore配置
#==============================================================
#RAMJobStore(基於內存)和JDBCJobStore用於在關係數據庫中存儲調度信息
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#必須配置,代表瞭解不同數據庫系統的特定“方言”。StdJDBCDelegate(用於完全符合JDBC的驅動程序)
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#數據庫表名的前綴,支持自定義
org.quartz.jobStore.tablePrefix = QRTZ_
#在被認爲“失火”之前,調度程序將“容忍”一個Triggers將其下一個啓動時間通過的毫秒數
org.quartz.jobStore.misfireThreshold = 60000
#在給定的通行證中,工作區將處理的最大錯誤次數觸發。
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
#設置爲“true”以打開羣集功能
org.quartz.jobStore.isClustered = true
# 檢測羣集中的其他實例的頻率(以毫秒爲單位)。
org.quartz.jobStore.clusterCheckinInterval = 20000
# 此屬性的值必須是配置屬性文件中定義的DataSource的名稱
org.quartz.jobStore.dataSource = myDS
#配置數據源
#數據庫中quartz表的表名前綴
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/school?serverTimezone=GMT&characterEncoding=utf-8
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = 123456
org.quartz.dataSource.myDS.maxConnections = 5
spring集成quartz
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import com.study.FirstSpringBoot.service.PrintTask;
import com.study.FirstSpringBoot.service.PrintTask2;
@Configuration
public class QuartzConfig {
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
// 註冊定時觸發器
schedulerFactoryBean.setTriggers(cronTriggerFactoryBean1().getObject(), cronTriggerFactoryBean2().getObject());
// QuartzScheduler 啓動時更新己存在的Job,這樣就不用每次修改targetObject後刪除qrtz_job_details表對應記錄了
schedulerFactoryBean.setOverwriteExistingJobs(true);
// QuartzScheduler 延時啓動,應用啓動完後 QuartzScheduler 再啓動
schedulerFactoryBean.setStartupDelay(1);
// 設置加載的配置文件
schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties"));
return schedulerFactoryBean;
}
@Bean
public CronTriggerFactoryBean cronTriggerFactoryBean1() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
// 定時觸發器綁定任務
cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean1().getObject());
cronTriggerFactoryBean.setCronExpression("0/30 * * * * ?");
cronTriggerFactoryBean.setGroup("TiggerGroup1");
return cronTriggerFactoryBean;
}
@Bean
public JobDetailFactoryBean jobDetailFactoryBean1() {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setGroup("JobGroup1");
factory.setJobClass(PrintTask.class);
factory.setDurability(true);
return factory;
}
@Bean
public CronTriggerFactoryBean cronTriggerFactoryBean2() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
// 定時觸發器綁定任務
cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean2().getObject());
cronTriggerFactoryBean.setCronExpression("0 0/1 * * * ?");
cronTriggerFactoryBean.setGroup("TiggerGroup2");
return cronTriggerFactoryBean;
}
@Bean
public JobDetailFactoryBean jobDetailFactoryBean2() {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setGroup("JobGroup2");
factory.setJobClass(PrintTask2.class);
// 該屬性必須爲true,否則報錯 'Jobs added with no trigger must be durable'
factory.setDurability(true);
return factory;
}
}
上面配置了兩個任務,第一個任務每隔30秒輸出print1111111
,第二個任務每隔1分鐘輸出print2222222
public class PrintTask extends QuartzJobBean {
private Logger log = LoggerFactory.getLogger(PrintTask.class);
@Override
protected void executeInternal(final JobExecutionContext context) throws JobExecutionException {
log.info("print1111111");
}
}