[Quartz] Quartz storage and persistence-based on the quartz. properties configuration, quartz persistence

Source: Internet
Author: User

[Quartz] Quartz storage and persistence-based on the quartz. properties configuration, quartz persistence

 

Original works of Lin bingwen Evankaka. Reprinted please indicate the source http://blog.csdn.net/evankaka

I. Quartz storage and persistence

Quartz provides two basic job Storage types. The first type is RAMJobStore, and the second type is JDBC job storage. By default, Quartz saves the running information of task scheduling in the memory, which provides the best performance because the data access in the memory is the fastest. The disadvantage is the lack of data persistence. When the program stops or the system crashes, all running information is lost.

For example, if we want to schedule a task to run for 100 times, if the system crashes after 50 times, the task execution counter starts from 0 when the system restarts. In most practical applications, we often do not need to save the on-site data of task scheduling, because we seldom need to plan a task with a specified number of executions. For a task that only executes once, the execution condition information itself should be persistent business data (for example, if the task is locked for expiration, the unlock time should be business data ), after the execution is complete, the condition information changes accordingly. Of course, the scheduling site information not only records the number of running times, but also includes scheduling rules and data in JobDataMap.

If you really need to persist the task scheduling information, Quartz allows you to save the information to the database by adjusting its attribute file. After the database is used to save the task scheduling information, even if the system crashes and restarts, the task scheduling information will be restored. As in the previous example, after 50 crashes, the counter starts counting from 51. A task that uses the database to save information is called a persistent task.

Comparison

Type

Advantages

Disadvantages

RAMJobStore

No external database, easy configuration and fast running

Because the scheduler information is stored in the memory allocated to the JVM, when the application stops running, all the scheduling information will be lost. In addition, the number of jobs and triggers that can be stored in the JVM memory is limited.

JDBC job Storage

Clusters are supported because all task information is saved to the database, which can control the transaction. In addition, if the application server is closed or restarted, the task information will not be lost, in addition, you can resume tasks that fail to be executed due to server shutdown or restart.

The speed of running depends on the speed of connecting to the database


Ii. Quartz storage instance


The implementation steps are as follows:


2.1 create a data storage table

Because you need to save the quartz data to the database, you need to create a relevant database. You can find the corresponding SQL script from the downloaded quartz package. Currently, mysql, DB2, oracle, and other mainstream databases are supported. You can select the appropriate script for running based on the project requirements.

My project is mysql, and a quartz database is created in the data, and then the table is created by executing the tables_mysql_innodb. SQL script.The script file is located at: E: \ JarCom \ quartz-2.2.1 \ docs \ dbTables (the directory will be different according to your Quartz directory)

Then open the MySql terminal:

First, create a database named quartz;

Then execute the script:

Running result:

First, the following error occurs:

Four data tables failed to be created.

Solution:

Replace all TYENGINEPE = InnoDB in tables_mysql_innodb. SQL with ENGINE = InnoDB;

Execute again:


Indicates that the database table is successfully created.


After the table is created, you can see the relevant table

+ --------- +
| Tables_in_quartz |
+ --------- +
| QRTZ_BLOB_TRIGGERS |
| QRTZ_CALENDARS |
| QRTZ_CRON_TRIGGERS |
| QRTZ_FIRED_TRIGGERS |
| QRTZ_JOB_DETAILS |
| QRTZ_LOCKS |
| QRTZ_PAUSED_TRIGGER_GRPS |
| QRTZ_SCHEDULER_STATE |
| QRTZ_SIMPLE_TRIGGERS |
| QRTZ_SIMPROP_TRIGGERS |
| QRTZ_TRIGGERS |
+ --------- +

2.2 create a project and import the package

Create a java project and import relevant jar packages

I will not talk about it here. You can download it from the official website. This article uses the latest 2, 2.1

Quartz: http://www.quartz-scheduler.org/

And mySql operation package, and a commons-lang Package, the final directory of the work is as follows:


Then, add the corresponding configuration in the project. 2.3 first, the quartz. properties configuration

# Default Properties file for use by StdSchedulerFactory # to create a Quartz Scheduler Instance, if a different # properties file is not explicitly specified. # cluster configuration org. quartz. scheduler. instanceName: DefaultQuartzSchedulerorg. quartz. scheduler. rmi. export: falseorg. quartz. scheduler. rmi. proxy: falseorg. quartz. scheduler. wrapJobExecutionInUserTransaction: false org. quartz. threadPool. class: org. quartz. simpl. simpleThreadPoolorg. quartz. threadPool. threadCount: 10org. quartz. threadPool. threadPriority: 5org. quartz. threadPool. threadsInheritContextClassLoaderOfInitializingThread: true org. quartz. jobStore. misfireThreshold: 60000 #=================================================== ============================================= # Configure jobStore #=============================================== ============================================= # default configuration, save data to memory # org. quartz. jobStore. class: org. quartz. simpl. RAMJobStore # persistent configuration org. quartz. jobStore. class: org. quartz. impl. jdbcjobstore. jobStoreTXorg. quartz. jobStore. driverDelegateClass: org. quartz. impl. jdbcjobstore. stdJDBCDelegateorg. quartz. jobStore. useProperties: true # database table prefix # org. quartz. jobStore. tablePrefix: qrtz _ # org. quartz. jobStore. dataSource: qzDS #=============================================== ============================================= # Configure datasources #================================================= ============================================= # JDBC driver # org. quartz. dataSource. qzDS. driver: com. mysql. jdbc. driver # org. quartz. dataSource. qzDS. URL: jdbc: mysql: // localhost: 3306/quartz # org. quartz. dataSource. qzDS. user: root # org. quartz. dataSource. qzDS. password: christmas258 @ # org. quartz. dataSource. qzDS. maxConnection: 10

Here, org. quartz. jobStore. class indicates that the persistence of quartz is saved by the database,

Org. quartz. jobStore. driverDelegateClass is different based on the selected database type. Here I am using mysql, so it is org. quartz. impl. jdbcjobstore. StdJDBCDelegate.

The attribute configuration file of Quartz mainly includes three aspects:

1) cluster information;

2) scheduler thread pool;

3) Save the on-site data for task scheduling.

· Scheduler attributes

The first part has two rows, respectively setting the Instance name (instanceName) and instance ID (instanceId) of the scheduler ). The org. quartz. scheduler. instanceName attribute can be any string you like. Multiple schedulers are used to differentiate specific schedulers. Multiple schedulers are usually used in the cluster environment. Now, set the following string: org. quartz. scheduler. instanceName: DefaultQuartzScheduler. In fact, this is also the default value when you do not configure this attribute.

The second attribute of the scheduler is org. quartz. schedid. instanceId. Like the instaneName attribute, the instanceId attribute also allows any string. This value must be unique among all scheduler instances, especially in a cluster. If you want Quartz to help you generate this value, you can set it to AUTO. If the Quartz framework runs in a non-cluster environment, the automatically generated value will be NON_CLUSTERED. If Quartz is used in the cluster environment, this value will be the host name plus the current date and time. In most cases, set it to AUTO.
· Thread pool attributes

The next part is to set the attribute values necessary for the thread. These threads run in Quartz to take responsibility in the background. The threadCount attribute controls how many worker threads are created to process jobs. In principle, the more jobs you want to process, the more worker threads you need. The value of threadCount must be at least 1. Quartz does not limit the maximum number of worker threads you set. However, if you set this value to more than 100 on most machines, it will become quite impractical, especially when your Job has been executed for a long time. This item has no default value, so you must set a value for this property.

The threadPriority attribute sets the priority of the worker thread. Threads with higher priority give higher priority to execution than threads with lower priority. The maximum value of the threadPriority attribute is the constant java. lang. Thread. MAX_PRIORITY, which is equal to 10. The minimum value is the constant java. lang. Thread. MIN_PRIORITY, which is 1. The normal value of this attribute is Thread. NORM_PRIORITY, which is 5. In most cases, set it to 5, which is also the default value of this attribute.

The last thread pool attribute to be set is org. quartz. threadPool. class. This value is the name of a class that implements the org. quartz. spi. ThreadPool interface. The org Z built-in thread pool implementation class is org. Quartz. smpl. SimpleThreadPool, which can meet the needs of most users. The implementation of this thread pool has simple behavior and has been well tested. It provides a fixed thread pool in the life cycle of the scheduler. You can create your own thread pool implementation as needed. This may be required if you want a on-demand scalable thread pool. This property has no default value. You must specify a value for it.

· Job storage settings

The settings in the Job Storage section describe how the Job and Trigger information is stored during the life cycle of the scheduler instance. We haven't talked about job storage and its purpose yet; because it is not necessary for the current example, we will leave it for further explanation. Now, what you need to know is that we can store the scheduler information in the memory instead of in the relational database.

Storing the scheduler information in the memory is fast and easy to configure. Once the scheduler process is terminated, the statuses of all jobs and triggers are lost. To store jobs in memory, you must set the org. quartz. jobStrore. class Attribute to org. quartz. simpl. RAMJobStore. If we do not want to lose the status information of the scheduler after the JVM exits, we can use relational databases to store this information. This requires another JobStore implementation, which will be discussed later. Chapter 5 "Cron Trigger and others" and chapter 6 "job storage and persistence" will refer to different types of job storage implementation you need.
2.4 create a Job class

package com.mucfc;import java.text.SimpleDateFormat;import java.util.Date;import org.apache.log4j.Logger;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;public class MyJob implements Job{private static final Logger logger = Logger.getLogger(MyJob.class);  @Overridepublic void execute(JobExecutionContext context)throws JobExecutionException {System.out.println("Hello quzrtz  "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ").format(new Date()));}}
2.5. Execution class for creating a Job:

Package com. mucfc; import java. text. parseException; import java. util. list; import org. apache. commons. lang. stringUtils; import org. quartz. cronScheduleBuilder; import org. quartz. job; import org. quartz. jobBuilder; import org. quartz. jobDetail; import org. quartz. jobKey; import org. quartz. scheduler; import org. quartz. schedulerException; import org. quartz. schedulerFactory; import org. quartz. simpleScheduleBuilder; import org. quartz. simpleTrigger; import org. quartz. trigger; import org. quartz. triggerBuilder; import org. quartz. triggerKey; import org. quartz. impl. stdSchedulerFactory; import org. springframework. beans. factory. annotation. autowired; import org. springframework. context. applicationContext; import org. springframework. context. support. classPathXmlApplicationContext; public class QuartzTest {private static SchedulerFactory sf = new StdSchedulerFactory (); private static String JOB_GROUP_NAME = "ddlib"; private static String TRIGGER_GROUP_NAME = "ddlibTrigger "; public static void main (String [] args) throws SchedulerException, ParseException {startSchedule (); // resumeJob ();}/*** start a simpleSchedule () schedule */public static void startSchedule () {try {// 1. Create a JobDetail instance and specify QuartzJobDetail jobDetail = JobBuilder. newJob (MyJob. class) // task execution class. withIdentity ("job1_1", "jGroup1") // Task Name, task group. build (); // 2. Create TriggerSimpleScheduleBuilder builder = SimpleScheduleBuilder. simpleSchedule () // sets the number of executions. repeatSecondlyForTotalCount (100); Trigger trigger = TriggerBuilder. newTrigger (). withIdentity ("trigger1_1", "tGroup1 "). startNow (). withSchedule (builder ). build (); // 3. Create SchedulerScheduler scheduler = StdSchedulerFactory. getdefaschscheduler (); scheduler. start (); // 4. Schedule and execute scheduler. scheduleJob (jobDetail, trigger); try {Thread. sleep (60000);} catch (InterruptedException e) {e. printStackTrace ();} scheduler. shutdown ();} catch (SchedulerException e) {e. printStackTrace () ;}}/*** locate an existing job from the database and reschedule the new account */public static void resumeJob () {try {SchedulerFactory schedulerFactory = new StdSchedulerFactory (); Scheduler scheduler = schedulerFactory. getsched (); // ① obtain the List of all trigger groups in the scheduler <String> triggerGroups = schedups. getTriggerGroupNames (); // ② re-recover the trigger named trigger1_1 in the tgroup1 group for (int I = 0; I <triggerGroups. size (); I ++) {List <String> triggers = scheders. getTriggerGroupNames (); for (int j = 0; j <triggers. size (); j ++) {Trigger tg = schedtg. getTrigger (new TriggerKey (triggers. get (j), triggerGroups. get (I); // ②-1: Determine if (tg instanceof SimpleTrigger & tg. getDescription (). equals ("tgroup1.trigger1 _ 1") {// ②-1: resume running schedger. resumeJob (new JobKey (triggers. get (j), triggerGroups. get (I) ;}}} scheduler. start ();} catch (Exception e) {e. printStackTrace ();}}}
2.6. execution:

Open the database and enter

use quartz;select* from QRTZ_SIMPLE_TRIGGERS

Then, stop the above program and click the red box in the upper right corner.

Change the main code:

public static void main(String[] args) throws SchedulerException,ParseException {//startSchedule();resumeJob();}

Output result:


In addition, search for tables in the data:

It was found that there was a change .. TRIGGER_GROUP indicates the number of executions, and TRIGGER_GROUP indicates the number of calls

Stop the program and start the program again. The result is as follows.

After it is restarted, TRIGGER_GROUP becomes 39, which is counted from the number of times TRIGGER_GROUP was last run.


After 100 executions, the scheduling will be deleted from the data table:

The result is as follows:


At this time, the records in the table have become empty.

It is worth noting that if you use JDBC to save the task scheduling data, when you run the code

startSchedule();//resumeJob();
Then exit. When you want to run

startSchedule();//resumeJob();

The system will throw the JobDetail cognominal exception: Unable to store Job with name: 'job1 _ 1' and group: 'jgroup1', because one already exists with this identification. every Time Scheduler # scheduleJob () is called, Quartz saves JobDetail and Trigger information to the database. If JobDetail or Trigger with the same name already exists in the data table, an exception occurs.

Run again here as follows:

//startSchedule();resumeJob();


Iii. Notes

Some related meanings:

QRTZ_CALENDARS stores the Calendar information of Quartz as Blob. QRTZ_CRON_TRIGGERS stores Cron triggers, including Cron expressions and time zone information. QRTZ_FIRED_TRIGGERS stores status information related to triggered triggers, and associated Job execution information QRTZ_PAUSED_TRIGGER_GRPS stores paused Trigger group information QRTZ_SCHEDULER_STATE stores a small amount of information about schedgger status, and other schedgger instances (if used in a cluster) QRTZ_LOCKS stores program pessimistic lock information (if a pessimistic lock is used) QRTZ_JOB_DETAILS stores detailed information about each configured Job. Worker stores information about the configured JobListener. QRTZ_SIMPLE_TRIGGERS stores simple triggers, including repeat times, interval, and number of hits QRTZ_BLOG_TRIGGERS Trigger as Blob storage (for Quartz users to create their own Custom Trigger type with JDBC, JobStore does not know how to store instances) QRTZ_TRIGGER_LISTENERS stores the information of the configured TriggerListener QRTZ_TRIGGERS stores the information of the configured Trigger

Bytes --------------------------------------------------------------------------------------------------
The fields in the quartz persistent database are used to explain how to create tables. The SQL statement can be found in the dbTables folder. This section describes the main tables:
Table qrtz_job_details: stores the job details. You need to initialize job_name: name of the job in the cluster according to the actual situation. You can customize the name as needed without forcing job_group: the name of the group to which the job belongs in the cluster. The name can be customized by the user without forcing job_class_name: The full package name of the notejob implementation class in the cluster, quartz finds the job class is_durable Based on the path to classpath: whether it is persistent. If this attribute is set to 1, quartz will persist the job to job_data: A blob field in the database, store the persistent job object table qrtz_triggers: saves the trigger information trigger_name: name of the trigger, which can be customized by the user without forcing the trigger_group: name of the group to which the trigger belongs, this name is customized by the user at will and does not require job_name: qrtz_job_details table job_name foreign key job_group: qrtz_job_details table job_group foreign key trigger_state: current trigger status, set to ACQUIRED, if it is set to WAITING, the job will not trigger_cron: trigger type. The cron expression table qrtz_cron_triggers: stores the foreign key trigger_name: qrtz_triggers table trigger_name trigger_group: cron_expression: cron expression table qrtz_scheduler_state: stores the note instance information in the cluster. quartz regularly reads the information of the table to determine the current status of each instance in the cluster. instance_name: org. quartz. scheduler. this field is written to the instanceId configuration name. If it is set to AUTO, quartz will generate a name named last_checkin_time based on the physical machine name and the current time: Last check time checkin_interval: Check Interval


Configure the quartz. properties file:
# The same org. quartz. scheduler. instanceName: scheduler # ID is set to automatically obtain each org. quartz. scheduler. instanceId: AUTO # The data storage method is persistent org. quartz. jobStore. class: org. quartz. impl. jdbcjobstore. jobStoreTX # database platform org. quartz. jobStore. driverDelegateClass: org. quartz. impl. jdbcjobstore. oracle. weblogic. webLogicOracleDelegate # obtain the database alias org. quartz. jobStore. dataSource: myXADS # table prefix org. quartz. jobStore. tablePref Ix: QRTZ _ # setting to TRUE does not cause the class version issue org. quartz. jobStore. useProperties: true # Add to cluster org. quartz. jobStore. isClustered: true # Check Interval for failed scheduling instances org. quartz. jobStore. clusterCheckinInterval: 20000 # maximum allowed job extension org. quartz. jobStore. misfireThreshold: 60000 # ThreadPool implementation class name org. quartz. threadPool. class: org. quartz. simpl. simpleThreadPool # Number of threads org. quartz. threadPool. threadCount: 10 # thread priority org. quartz. threadPoo L. threadPriority: 5 # create a parent thread org. quartz. threadPool. threadsInheritContextClassLoaderOfInitializingThread: true # Set the data source org. quartz. dataSource. myXADS. jndiURL: CT # jbdi class name org. quartz. dataSource. myXADS. java. naming. factory. initial: weblogic. jndi. WLInitialContextFactory # URLorg. quartz. dataSource. myXADS. java. naming. provider. url: = t3: // localhost: 7001 [note]: In the J2EE project, if you want to use a database to manage information related to Quartz, you must configure the data source. This is the requirement of Quartz.

Original works of Lin bingwen Evankaka. Reprinted please indicate the source http://blog.csdn.net/evankaka


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.