1. 程式人生 > >集群環境下如何防止定時任務重復執行?

集群環境下如何防止定時任務重復執行?

mysql spa clas job 每天 如果 varchar 郵件發送 表示

起因
最近做項目是遇到這樣一個問題:系統需要在每天的16:00向一些符合特定條件的用戶發送一份郵件,發送成功後修改掉數據庫中對應數據的標誌位。本來是沒有問題的,但後來系統被部署到了集群環境下,導致每天會向這些用戶發送多次同樣的數據,遭到了客戶的抱怨。
解決
下面來介紹一下處理這種問題的解決辦法:
1.在數據庫中建立tm_job_group表

NameTypeComments
group_id number 組id
interval number 時間間隔
區分定時任務的間隔
即多長時間內不可重復執行,單位分鐘
remark varchar2(100) 描述

數據如下:

group_idintervalremark
1 1440 24小時執行一次
2 60 1小時執行一次
3 120 2小時執行一次

2.在數據庫中建立一張tm_job表,用來存儲定時任務的信息

NameTypeComments
job_id number 定時任務的id
job_name varchar2(100) 定時任務的名稱
job_group number 定時任務所屬的組
remark varchar(100) 備註

數據如下:

job_idjob_namejob_groupremark
1 催辦郵件發送Job 1 每天16點執行

3.建立ts_job_log表

NameTypeComments
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,’正常’);
會報錯
如果在代碼中捕獲到錯誤就不執行定時任務中的操作。

總結
這種方法就是通過讓數據庫中的操作受到約束條件產生異常來實現的。

集群環境下如何防止定時任務重復執行?