集群環境下如何防止定時任務重復執行?
起因
最近做項目是遇到這樣一個問題:系統需要在每天的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,’正常’);
會報錯
如果在代碼中捕獲到錯誤就不執行定時任務中的操作。
總結
這種方法就是通過讓數據庫中的操作受到約束條件產生異常來實現的。
集群環境下如何防止定時任務重復執行?