Lesson 9: Job Stores

JobStore’s are responsible for keeping track of all the “work data” that you give to the scheduler: jobs, triggers, calendars, etc. Selecting the appropriate JobStore for your Quartz scheduler instance is an important step. Luckily, the choice should be a very easy one once you understand the differences between them. You declare which JobStore your scheduler should use (and it’s configuration settings) in the properties file (or object) that you provide to the SchedulerFactory that you use to produce your scheduler instance.

Never use a JobStore instance directly in your code. For some reason many people attempt to do this. The JobStore is for behind-the-scenes use of Quartz itself. You have to tell Quartz (through configuration) which JobStore to use, but then you should only work with the Scheduler interface in your code.

RAMJobStore

RAMJobStore is the simplest JobStore to use, it is also the most performant (in terms of CPU time). RAMJobStore gets its name in the obvious way: it keeps all of its data in RAM. This is why it’s lightning-fast, and also why it’s so simple to configure. The drawback is that when your application ends (or crashes) all of the scheduling information is lost - this means RAMJobStore cannot honor the setting of “non-volatility” on jobs and triggers. For some applications this is acceptable - or even the desired behavior, but for other applications, this may be disastrous.

To use RAMJobStore (and assuming you’re using StdSchedulerFactory) simply specify the class name org.quartz.simpl.RAMJobStore as the JobStore class property that you use to configure quartz:

Configuring Quartz to use RAMJobStore


org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

There are no other settings you need to worry about.

JDBCJobStore

JDBCJobStore is also aptly named - it keeps all of its data in a database via JDBC. Because of this it is a bit more complicated to configure than RAMJobStore, and it also is not as fast. However, the performance draw-back is not terribly bad, especially if you build the database tables with indexes on the primary keys. On fairly modern set of machines with a decent LAN (between the scheduler and database) the time to retrieve and update a firing trigger will typically be less than 10 milliseconds.

JDBCJobStore works with nearly any database, it has been used widely with Oracle, PostgreSQL, MySQL, MS SQLServer, HSQLDB, and DB2. To use JDBCJobStore, you must first create a set of database tables for Quartz to use. You can find table-creation SQL scripts in the “docs/dbTables” directory of the Quartz distribution. If there is not already a script for your database type, just look at one of the existing ones, and modify it in any way necessary for your DB. One thing to note is that in these scripts, all the the tables start with the prefix “QRTZ_” (such as the tables “QRTZ_TRIGGERS”, and “QRTZ_JOB_DETAIL”). This prefix can actually be anything you’d like, as long as you inform JDBCJobStore what the prefix is (in your Quartz properties). Using different prefixes may be useful for creating multiple sets of tables, for multiple scheduler instances, within the same database.

Once you’ve got the tables created, you have one more major decision to make before configuring and firing up JDBCJobStore. You need to decide what type of transactions your application needs. If you don’t need to tie your scheduling commands (such as adding and removing triggers) to other transactions, then you can let Quartz manage the transaction by using JobStoreTX as your JobStore (this is the most common selection).

If you need Quartz to work along with other transactions (i.e. within a J2EE application server), then you should use JobStoreCMT - in which case Quartz will let the app server container manage the transactions.

The last piece of the puzzle is setting up a DataSource from which JDBCJobStore can get connections to your database. DataSources are defined in your Quartz properties using one of a few different approaches. One approach is to have Quartz create and manage the DataSource itself - by providing all of the connection information for the database. Another approach is to have Quartz use a DataSource that is managed by an application server that Quartz is running inside of - by providing JDBCJobStore the JNDI name of the DataSource. For details on the properties, consult the example config files in the “docs/config” folder.

To use JDBCJobStore (and assuming you’re using StdSchedulerFactory) you first need to set the JobStore class property of your Quartz configuration to be either org.quartz.impl.jdbcjobstore.JobStoreTX or org.quartz.impl.jdbcjobstore.JobStoreCMT - depending on the selection you made based on the explanations in the above few paragraphs.

Configuring Quartz to use JobStoreTx


org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX

Next, you need to select a DriverDelegate for the JobStore to use. The DriverDelegate is responsible for doing any JDBC work that may be needed for your specific database. StdJDBCDelegate is a delegate that uses “vanilla” JDBC code (and SQL statements) to do its work. If there isn’t another delegate made specifically for your database, try using this delegate - we’ve only made database-specific delegates for databases that we’ve found problems using StdJDBCDelegate with (which seems to be most!). Other delegates can be found in the “org.quartz.impl.jdbcjobstore” package, or in its sub-packages. Other delegates include DB2v6Delegate (for DB2 version 6 and earlier), HSQLDBDelegate (for HSQLDB), MSSQLDelegate (for Microsoft SQLServer), PostgreSQLDelegate (for PostgreSQL), WeblogicDelegate (for using JDBC drivers made by Weblogic), OracleDelegate (for using Oracle), and others.

Once you’ve selected your delegate, set its class name as the delegate for JDBCJobStore to use.

Configuring JDBCJobStore to use a DriverDelegate


org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate

Next, you need to inform the JobStore what table prefix (discussed above) you are using.

Configuring JDBCJobStore with the Table Prefix


org.quartz.jobStore.tablePrefix = QRTZ_

And finally, you need to set which DataSource should be used by the JobStore. The named DataSource must also be defined in your Quartz properties. In this case, we’re specifying that Quartz should use the DataSource name “myDS” (that is defined elsewhere in the configuration properties).

Configuring JDBCJobStore with the name of the DataSource to use


org.quartz.jobStore.dataSource = myDS
If your Scheduler is busy (i.e. nearly always executing the same number of jobs as the size of the thread pool, then you should probably set the number of connections in the DataSource to be the about the size of the thread pool + 2.
The "org.quartz.jobStore.useProperties" config parameter can be set to "true" (defaults to false) in order to instruct JDBCJobStore that all values in JobDataMaps will be Strings, and therefore can be stored as name-value pairs, rather than storing more complex objects in their serialized form in the BLOB column. This is much safer in the long term, as you avoid the class versioning issues that there are with serializing your non-String classes into a BLOB.

TerracottaJobStore

TerracottaJobStore provides a means for scaling and robustness without the use of a database. This means your database can be kept free of load from Quartz, and can instead have all of its resources saved for the rest of your application.

TerracottaJobStore can be ran clustered or non-clustered, and in either case provides a storage medium for your job data that is persistent between application restarts, because the data is stored in the Terracotta server. It’s performance is much better than using a database via JDBCJobStore (about an order of magnitude better), but fairly slower than RAMJobStore.

To use TerracottaJobStore (and assuming you’re using StdSchedulerFactory) simply specify the class name org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore as the JobStore class property that you use to configure quartz, and add one extra line of configuration to specify the location of the Terracotta server:

Configuring Quartz to use TerracottaJobStore


org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore
org.quartz.jobStore.tcConfigUrl = localhost:9510

More information about this JobStore and Terracotta can be found at http://www.terracotta.org/quartz


         JobStore是负责跟踪调度器中所有的工作数据:作业任务、触发器、日历等。为你的Quartz调度器实例选择一个适当的JobStore是非常重要的一步。幸运的是,一旦你理解了这些JobStore之间的区别,选择它们是非常容易的事。你可以在配置文件(或是类对象)中定义调度器使用哪种JobStore,这个JobStore将会提供给SchedulerFactory,用来创建你的调度器实例。

        不要在你的代码中直接使用JobStore实例,因为一些原因许多开发者尝试这样做。JobStore是给Quartz在幕后使用的。你只需要通过配置信息告知Quartz该用哪个JobStore,然后在你的代码里只需要使用调度器接口即可。

RAMJobStore

         RAMJobStore是最容易使用的JobStore,它也是最高效的(从CPU时间计算)。从RAMJobStore的名字可以明显地发现:它将所有数据存储在RAM中。这就是为什么它速度快并且配置简单的原因。缺点是当你的应用终止(或是崩溃)时,所有的调度信息都会丢失——这意味着RAMJobStore会导致作业任务和触发器的non-volatility设置不起作用。对某些应用来说,这种缺点可以接受,甚至需要这样的特性,但对另外一些应用来说,这种缺点可能会成为一个灾难。

       假定你正在使用StdSchedulerFactory,想要使用RAMJobStore时,只需要在Quartz配置文件中将JobStore class参数的值指定为org.quartz.simpl.RAMJobStore的类全名即可:

       Quartz配置文件中使用RAMJobStore


org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore  

这里再没有别的设置需要你去操心了。

JDBCJobStore

         JDBCJobStore同样人如其名——它通过JDBC将所有的数据保存在数据库中。正因为如此配置JDBCJobStore要比RAMJobStore复杂许多,并且也没RAMJobStore速度快。然而,后台的执行效率也不是非常糟糕,特别是如果你在数据库的主键中创建索引,就可以提高效率。比较好的局域网环境内的现代标准配置的机器,恢复和更新一个触发器所需要花费的时间一般在10毫秒以内。

         JDBCJobStore几乎可以适用于任何数据库,它已经在Oracle,PostgreSQL, MySQL, MS SQLServer, HSQLDB DB2数据库中广泛使用。为了使用JDBCJobStore,你必须先创建一套数据库表供Quartz使用。你可以在Quartz发布包的“docs/dbTables”目录找到建表SQL脚本。如果现成的脚本不适合你的数据库类型,找到其中一个脚本,想尽一切必要的方法修改成适合你的数据库。需要注意一点是在这些脚本中,所有表的前缀都是“QRTZ_”(例如表“QRTZ_TRIGGERS”和“QRTZ_JOB_DETAIL”)。这个前缀实际上可以是任何你想要的。只要你告诉JDBCJobStore前缀是什么(在Quartz配置文件里)。使用不同的前缀可能用来在同一个数据库中创建多套数据表,供多个调度器实例使用。

        一旦你创建了数据表,在配置和触发JDBCJobStore之前你需要作多个重要决定。你需要决定你的应用需要什么类型的事务。如果你不需要把调度命令(例如添加和移除触发器)和其他事务捆绑在一起,那么你就让Quartz使用JobStoreTx作为JobStore管理事务(这个是最常用的选择)。

        如果你需要Quartz关联其他事务(例如在J2EE应用服务器中),然后你应该使用JobStoreCMT——这种情况下Quartz会让应用服务容器管理事务。

       最后一件难题是从JDBCJobStore中设置DataSource,用来获得数据库的连接。数据源在Quartz配置中定义,从几种不同方式中选择其中一种。一种方式是Quartz自己创建和管理数据源——通过提供所有的数据库连接信息。另一种方式是Quartz使用由Quartz运行所在的应用服务器中的数据源——将数据源的JNDI名字提供给JDBCJobStore。想了解更多参数的详细信息,请查阅“docs/config”文件夹的示例配置文件。

       假定你正在使用StdSchedulerFactory,想要使用JDBCJobStore时,只需要在Quartz配置文件中将JobStore class参数的值指定为org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.impl.jdbcjobstore.JobStoreCMT的类全名即可——你可以根据上面几段文字中的解释决定你的选择。

       Quartz配置文件中使用JobStoreTx

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX  

接下来,你需要选择DriverDelegateJobStore使用。DriverDelegate负责完成任何JDBC的工作,它需要和指定的数据库类型对应。StdJDBCDelegate是使用“vanillaJDBC代码和SQL语句完成工作的一种delegate。如果没有专门与你的数据库对应的delegate,尝试使用这个delegate——我们只是为数据库开发对应的delegates,并且已经发现使用StdJDBCDelegate的问题(好像是问题最多的)。其他的delegates可以在org.quartz.impl.jdbcjobstore包或子包中找到。其他的delegates包括DB2v6Delegate(DB2 6及更早版本), HSQLDBDelegate (HSQLDB数据库), MSSQLDelegate(微软SQLServer数据库),PostgreSQLDelegate (PostgreSQL数据库), WeblogicDelegate (使用Weblogic JDBC的数据库), OracleDelegate(Oracle数据库)和其他。

       一旦你选择了delegates,设置delegate的类全名给JDBCJobStore使用。

       使用DriverDelegate配置JDBCJobStore

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate  

 接下来,你需要通知 JobStore 你使用的表前缀(前面讨论过)配置 JDBCJobStore 的表前缀
org.quartz.jobStore.tablePrefix = QRTZ_  

  最后,你需要设置JobStore使用哪个数据源。数据源的名字也必须在Quartz配置中定义。既然这样,我们指定Quartz的数据源的名字为“myDS”(即在配置文件另外的参数中定义)。

    配置JDBCJobStore的数据源名字:

org.quartz.jobStore.dataSource = myDS 

如果调度器繁忙(例如几乎总是执行跟线程池一样多的作业任务),你可能需要设置数据源的连接数,大约比线程池数多2个。

org.quartz.jobStore.useProperties配置参数可以设置为“true”(默认为false),为了通知JDBCJobStore所有在JobDataMaps的值都会为String类型,因此可以作为键值对存储,而不是在BLOB列中存储序列化的对象。这从长远看来更安全,例如你可以避免将非String类对象序列化到BLOB中导致的类版本问题。

 

TerracottaJobStore

         TerracottaJobStorer提供了一种不需要使用数据的可伸缩,健壮的方案。这意味着数据库在Quartz方面可以保持空载,而是将所有的资源保存在应用的其他部分中。

         TerracottaJobStore可以在集群或非集群环境中运行,在任何一种环境下,应用服务器重启期间都提供一个永久存储job数据的介质,因为这些数据存储在Terracotta服务器中。这个比通过JDBCJobStore使用数据库的方式高效(大约高一个数量级),但比RAMJobStore慢。

       假定你正在使用StdSchedulerFactory,想要使用TerracottaJobStore时,只需要在Quartz配置文件中将类名JobStore class参数的值指定为org.quartz.jobStore.class= org.terracotta.quartz.TerracottaJobStore,并且额外加一行配置指定Terracotta服务器地址。

    使用Terracotta配置Quartz

org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore  
org.quartz.jobStore.tcConfigUrl = localhost:9510  
 更多关于 JobStore Terracotta 的信息可以在这里找到: http://www.terracotta.org/quartz


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值