一般动作
登录
Wiki: BROPEN ▼: Document Index
»
Space: FAQ ▼: Document Index
»
Page: 集群环境下，如何使用锁（Locker）来避免计划任务（Quartz）执行冲突
搜索
zh
页面动作
导出 ▼: 以PDF格式导出 以RTF格式导出 以HTML格式导出
更多动作 ▼: 打印预览 察看源码
欢迎进入Wiki » FAQ » 集群环境下，如何使用锁（Locker）来避免计划任务（Quartz）执行冲突?

# 集群环境下，如何使用锁（Locker）来避免计划任务（Quartz）执行冲突?

在2013-11-25 16:18上被李小翔修改
评论 (0) · 附件 (0) · 记录 · 信息

默认情况下：

- Quartz 任务都是保存在内存中的，因此在集群环境下，不可避免的会出现相同的任务同时执行的情况；
- 如果在 Config.groovy 中启用 quartz.jdbcStore 将任务保存到数据库，并设置任务（XxxxJob）的属性 concurrent 为 false，则可以支持集群环境下不允许同时运行多个相同的任务；
- 进一步，如果多个应用设置不同的实例名称（quartz.props.scheduler.instanceName），则可以支持同名应用的集群不允许同时运行多个相同的任务，而不同应用的集群可以同时运行相同的任务。

但是，在实际运行过程中，效果却不甚理想，总是出现一些莫名的错误。

所以在常规的 J2EE 应用开发中，通常是把 quartz 任务单独作为一个 war 包部署，甚至部署到独立的 jvm 中，以避免各种冲突。

BroFramework 中提供了一套基于数据库的Lock API，使用这套API，可以灵活的处理 Quartz 中的任务执行冲突，并且实现各种 Quartz 原本无法实现的策略。

考虑下面的几个场景中，应用 Foo 和应用 Bar 中，有一个同名的 FoobarJob，这两个应用使用同一套 BroFramework 数据库：

1、希望同时只有一个 FoobarJob 执行：

import bropen.framework.core.Locker;
class FoobarJob {
/**
* 执行定时任务
*/
def execute() {
String lockKey = "FoobarJob"; // 按任务名加锁
if ( !Locker.lockExit(lockKey, false) ) return; // 加锁失败则直接退出
try {
// 任务执行代码
} finally {
Locker.unlock(lockKey, false); // 执行完毕，解锁
}
}
}

2、希望 Foo 和 Bar 的多个集群节点中只有一个 FoobarJob 执行，但是Foo、Bar两个应用可以同时运行 FoobarJob

import bropen.framework.core.Locker;
import bropen.framework.core.security.DomainApplication;
class FoobarJob {
/**
* 执行定时任务
*/
def execute() {
String lockKey = "FoobarJob_" + DomainApplication.current().id; // 按任务名和应用加锁
if ( !Locker.lockExit(lockKey, false) ) return; // 加锁失败则直接退出
try {
// 任务执行代码
} finally {
Locker.unlock(lockKey, false); // 执行完毕，解锁
}
}
}

3、如果有多个域（启用域管理后），可以在 lockKey 中添加域的ID（Domain.current().id）做为锁的关键字，以实现一个域的多个应用中，只允许运行一个同名的任务。

4、如果有两个任务会争用相同的资源，可以为两个任务设置相同的 lockKey，并且可以使用 lock 方法来代替 lockExit 方法，实现等待功能，如：

Locker.lock(lockKey, false, null, -1) // 一直等待

5、如果 FoobarJob 执行时，有自动发出邮件、生成待办等操作（比如每周三凌晨，给所有员工发出一个工作周报的待办任务），而且执行时长不等、执行间隔比较长（如大于半个小时），则在 execute 的 finally 中不解锁，而是让锁自动超时失效，以避免集群间极小的时间差导致任务多次重复执行，如：

def execute() {
String lockKey = "FoobarJob"; // 按任务名加锁
if ( !Locker.lockExit(lockKey, false, 30*60*1000) ) return; // 加锁失败则直接退出，否则加锁并设置超时时间为 30 分钟（默认）
// 任务执行代码，执行完后不解锁，让其自动超时失效
....
}
标签： BroFramework 锁 quartz
在2013-11-25 16:17上被李小翔创建

- 评论 （0）
- 附件 （0）
- 记录
- 信息

# 快速链接

- 首页
- 新闻动态
- FAQ

Copyright © 2013 北京博瑞开源软件有限公司
京ICP备12048974号