首页 > 代码库 > quartz(6)--集群

quartz(6)--集群

 Quartz应用能被集群,是水平集群还是垂直集群取决于你自己的需要。集群提供以下好处:

· 伸缩性

· 高可用性

· 负载均衡

目前,Quartz只能借助关系数据库和JDBC作业存储支持集群。

quartz集群架构

 

技术分享

 

quartz的分布式架构如上图,可以看到数据库是各节点上调度器的枢纽.各个节点并不感知其他节点的存在,只是通过数据库来进行间接的沟通。

实际上,quartz的分布式策略就是一种以数据库作为边界资源的并发策略.每个节点都遵守相同的操作规范,使得对数据库的操作可以串行执行.而不同名称的调度器又可以互不影响的并行运行。

集群配置

通过设置"org.quartz.jobStore.isClustered"属性为"true"来激活集群特性。
在集群中的每一个实例都必须有一 个唯一的"instance id" ("org.quartz.scheduler.instanceId" 属性), 但是应该有相同的"scheduler instance name" ("org.quartz.scheduler.instanceName"),也就是说集群中的每一个实例都必须使用相同的 quartz.properties 配置文件。

# Configure JobStore
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = rhinoDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000

锁机制

quartz通过数据库锁机制来实现集群,QRTZ_LOCKS就是Quartz集群实现同步机制的行锁表

表结构

技术分享

 

表记录

技术分享

关于行锁的机制:
1、mysql >  SET autocommit=0;    //先把mysql设置为不自动提交。
2、SELECT * FROM es_locks WHERE lock_name = ‘TRIGGER_ACCESS‘ FOR UPDATE ;     //线程一通过FOR UPDATE 可以把这行锁住
3、SELECT * FROM es_locks WHERE lock_name = ‘TRIGGER_ACCESS‘ FOR UPDATE ;     //线程二通过FOR UPDATE 无法获得锁,线程等待。
4、COMMIT;        //线程一通过COMMIT 释放锁
5、 //线程二可以访问到数据,线程不再等待。

所以,通过这个机制,一次只能有一个线程来操作 加锁 -  操作 - 释放锁。  如果 操作 的时间过长的话,会带来集群间的主线程等待。
数据库行锁是一种悲观锁,锁表时其它线程无法查询。

CALENDAR_ACCESS
JOB_ACCESS
MISFIRE_ACCESS
STATE_ACCESS
TRIGGER_ACCESS

QRTZ_LOCKS中有5条记录,代表5把锁,分别用于实现多个Quartz Node对Job、TRIGGER、Calendar访问的同步控制。目前代码中行锁只用到了STATE_ACCESS 和TRIGGER_ACCESS 这两种。

 

quartz(6)--集群