首页 > 代码库 > 集群环境下如何防止定时任务重复执行?
集群环境下如何防止定时任务重复执行?
起因
最近做项目是遇到这样一个问题:系统需要在每天的16:00向一些符合特定条件的用户发送一份邮件,发送成功后修改掉数据库中对应数据的标志位。本来是没有问题的,但后来系统被部署到了集群环境下,导致每天会向这些用户发送多次同样的数据,遭到了客户的抱怨。
解决
下面来介绍一下处理这种问题的解决办法:
1.在数据库中建立tm_job_group表
Name | Type | Comments |
---|---|---|
group_id | number | 组id |
interval | number | 时间间隔 区分定时任务的间隔 即多长时间内不可重复执行,单位分钟 |
remark | varchar2(100) | 描述 |
数据如下:
group_id | interval | remark |
---|---|---|
1 | 1440 | 24小时执行一次 |
2 | 60 | 1小时执行一次 |
3 | 120 | 2小时执行一次 |
2.在数据库中建立一张tm_job表,用来存储定时任务的信息
Name | Type | Comments |
---|---|---|
job_id | number | 定时任务的id |
job_name | varchar2(100) | 定时任务的名称 |
job_group | number | 定时任务所属的组 |
remark | varchar(100) | 备注 |
数据如下:
job_id | job_name | job_group | remark |
---|---|---|---|
1 | 催办邮件发送Job | 1 | 每天16点执行 |
3.建立ts_job_log表
Name | Type | Comments |
---|---|---|
job_log_id | number | job的logId,自增 |
job_id | number | 定时任务id |
job_group | number | 定时任务所属的组 |
job_start_time | date | 执行时间 |
job_status | varchar2(10) | 状态 执行情况 |
job_msg | varchar2(100) | 备注 |
这三张表的外键关联可以自己设定,这里就不写了。
然后为ts_job_log表添加如下的约束:
create unique index idx_ts_job_log_starttime on ts_job_log(job_id,decode(job_group,1,to_char(job_start_time,‘yyyymmdd‘),2,to_char(job_start_time,‘yyyymmddhh24‘),3,trunc(to_char(job_start_time,‘yyyymmddhh24‘)/2)),TO_CHAR(JOB_START_TIME,‘DD-MON-RR‘))
这个约束表示 当job_group为1时,在同一天不可以存在两个一样的job_id,当job_group为2时,在同一小时内不可存在两个相同的job_id,job_group为3时,在两个小时内不能出现同样的job_id.
时间比较的是job_start_time的时间间隔。
在执行定时任务的操作时,先向数据表中insert一条数据,如:
insert into ts_job_log(job_log_id,job_id,job_group,job_start_time,job_status)
values(1,1,1,sysdate,’正常’);
可以添加成功
当再执行如下操作时
insert into ts_job_log(job_log_id,job_id,job_group,job_start_time,job_status)
values(2,1,1,sysdate,’正常’);
会报错
如果在代码中捕获到错误就不执行定时任务中的操作。
总结
这种方法就是通过让数据库中的操作受到约束条件产生异常来实现的。
集群环境下如何防止定时任务重复执行?