Quartz是Java领域最著名的开原任务调度工具。Quartz提供了极为广泛的特性,如前文讲的持久化任务、本文将要介绍的集群,以及分布式任务等等。Quartz完全由Java编写,方面集成Spring;伸缩性、负载均衡和高可用的特点。

 

Quartz集群部署

Quartz集群中的每个节点是一个独立的Quartz应用,它又管理着其他的节点。该集群需要分别对每个节点分别启动或停止,不像应用服务器的集群,独立的Quartz节点并不与另一个节点或是管理节点通信。Quartz应用时通过数据库表来感知到另一个应用。只有使用持久化的JobStore才能完成Quartz集群。

 

PS:应用服务器的集群是每台服务器上,都部署相同的应用,通过类似于Apache这样的工具,来分摊应用服务器的访问压力;而Quartz的集群则不能使用类似的方式实现集群。

 

原理:

集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。目前集群只能工作在JDBC-JobStore(JobStore TX 或者JobStoreCMT)方式下,从本质上来说,是使集群上的每一个节点通过共享一个数据库来工作的。(Quartz启动两个维护线程,来维护数据库状态实现集群管理,一个是检测节点状态的线程,一个是恢复任务线程)。

(PS:这里大家想想为什么,只有集群持久化到数据库中,才可以做集群,而仅仅在内存中的定时任务,不可以做集群呢?其实答案显而易见。如果定时任务仅仅在内存中,那多台服务器之间,quartz一般不会进行通信,那么又如何做集群呢?而将job持久化在数据库中的定时任务则不然,上篇文章可查,在持久化后的数据库中,会生成很多张表。我们再想,quartz做了持久化,是如何保证集群高可用的呢?其实也很简单,是数据库做了一把全局的分布式锁(想想zookeeper)。某台服务器执行定时任务时,会在数据库中写入一条记录,执行完之后再释放。期间,其他服务器因为不可在写入记录,故其他服务器的quartz不可执行。也就是保证了:某一时刻,该quartz集群只有一太服务器在执行)

 

负载平衡是自动完成的,集群的每个节点会尽快触发任务。当一个触发器的出发时间达到时,第一个节点将会获得任务(通过锁定),称为执行任务的节点。

当任务触发时间开始时,每个实例上会并发获取一把锁(该锁是通过数据库表的全局锁实现的),谁先获得锁谁就先执行,其他节点的任务就不会执行任务。

如果一个节点挂掉了,而且任务被标记为recovery,就会被其他节点检测到重新执行这个任务;没有被标记的话,就会再一次任务触发的时候重新由其他节点执行。

故障切换的发生是在当一个节点正在执行一个或多个任务失败的时候。当一个节点失败了,其他的节点检测到,并且标识在失败节点上正在进行的数据库中的任务。任何被标记为可恢复的任务都是被其他的节点重新执行。没有标记可恢复的任务只会被释放出来,将会在下次相关触发器触发时执行。