java定时任务在服务器集群中的实现问题

三十回头 发布于 2016/01/21 13:04
阅读 2K+
收藏 1
如果一个应用程序有一个后台定时执行的任务,比如用quartz或者java.util.timer,那么当这个程序部署在服务器集群时,每一个服务器上都会执行这个后台任务。如果有3台应用服务器,那么这个任务就被执行了3次。
有没有什么方法,可以在在集群范围内,所有的定时任务只执行一次呢?
加载中
1
Erroooooor
Erroooooor

quartz有基于集群的实现方案的,官网有。通过mysql表锁的方式实现.

这上面也有介绍 http://sundoctor.iteye.com/blog/486055

0
飞到天空的猪
飞到天空的猪
每个服务器请求自己要的业务数据即可。
0
技术论坛来扯淡
自己找麻烦事情
三十回头
三十回头
还真不是 遇到这个问题了
0
妹子楼顶有鸽子
妹子楼顶有鸽子

1、最简单的每个任务的的hashcode mod 3 处理对应需要处理的服务器。

2、把任务放到缓存服务器中,处理完了就拿下一个 等等

0
panmingguang
panmingguang
很简单么, 给个指定那个服务器 后台运行 定时任务就好了, ip 定位一下, 或其他标记定位一下
0
三十回头
三十回头

引用来自“Erroooooor”的评论

quartz有基于集群的实现方案的,官网有。通过mysql表锁的方式实现.

这上面也有介绍 http://sundoctor.iteye.com/blog/486055

好的 谢谢了  我先试下 这几天遇到这个问题了  中午12点有个定时任务 3台服务器同时执行 日志看到同时都执行了 就是没有执行结果   应该是锁表了 而且执行的非常慢


0
GITTODO
GITTODO
用中间件
0
xfeiyu
xfeiyu

请教一下 我所遇到的集群问题,假设有一个定时任务执行时间预计为70秒(执行时间不可控),但是执行频率为每隔10秒一次,如何在同一个时刻保证集群中只有一个节点执行该定时job?

我认为若该job执行时间比较久,其他节点的定时任务都应该等待。

但是目前的现状是每个节点会串行的获取这个job的触发器,但是问题是第一个节点获取触发器之后正在执行job且还未执行完毕,第二个节点就能成功获取触发器,而且能执行job。我认为这个时候,第二个几点不应该成功获取触发器,也无法执行job才对。

已经看过quartz的源码,它为了保证串行获取触发器,使用数据库的qrtz_locks的悲观锁来控制,但是程序在读取完数据库中所有job相关信息后,会释放掉悲观锁,然后再执行job,这样就导致我遇到的问题,请教一个各位是否为我理解错误或者配置不正确导致?

xfeiyu
xfeiyu
回复 @三十回头 : 是的 我也遇到这个问题了,但是官网文档说可以,就是不知道哪配置有问题,总之现在好在定时任务压力不大,数量也不多,所以job内部增加悲观锁
三十回头
三十回头
目前我们集群的定时任务,是在一台服务器上执行的,除非定时任务能保证幂等性(几台服务器同时执行),要不会有问题
0
囿于昼夜

解决办法:

    若无需考虑效率,可在 redis 中加一个锁。在定时任务开头判断锁状态,若有锁,直接 return,没有锁的话则加上锁并向下执行,在任务执行的最后删除锁。

    若需要考虑效率就比较麻烦了,如几台服务器需要同时处理一个数据库中的数据,为了防止数据被重复处理,可做一个读取的定时任务,任务开头加锁,读取并 push 到一个 redis 队列中;再做一个处理的定时任务,pop redis 队列中的数据挨个进行处理,当 redis 队列被 pop 空以后,则把锁删掉。

    但这种处理方式仍有一定的几率遇到一台服务进入读取服务判断锁状态的时候另一台服务器正好处理完最后一条队列信息把锁删掉,导致锁失效的情况。然几率较小,且未想到更好的处理方式,目前我的程序仍在这样处理。

0
MrAYanG
MrAYanG

Quartz支持集群方式,会选出一个实例执行job。或者自己写,共用分布式存储(比如zk),监控节点状态,回调执行Job。

返回顶部
顶部