集群伺服器中定時任務多次執行的解決方案

2021-08-21 18:34:33 字數 1688 閱讀 8685

1、oracle

思路:insert表內容時,主鍵重複,無法插入

範圍:適用於執行頻率低的定時任務

方法:新建一張任務執行表,每次執行定時任務之前先insert該錶。

比如:每天執行一次批處理操作。主鍵可以設定為批處理name+日期(年月日)。集群伺服器可能會同時去insert該錶,而只有一台伺服器能插入成功,則只讓這一台伺服器執行該批處理任務。

2、redis

範圍:適用於執行頻率高的定時任務

有如下兩種思路方法:

思路1:採用的是redis中list的push和pop操作。因為redis是單執行緒,所有命令依次執行,所以不會出現多台伺服器同時訪問的情況。

方法:系統初始化時,向redis中lpush乙個list(key,1),作為標識flag。每台伺服器執行批處理之前,先去rpop該list,只有獲取到該標識的伺服器才能執行批處理任務,執行完畢後再lpush回乙個list(key,1)。

比如:執行任務前先執行rpopredisflag,任務完成後執行lpushredisflag.

public class autojobactdis extends quartzjobbean 

}/**

* 從快取中取得flag,獲取定時任務執行許可權

** @param rediskey

* @return

*/public boolean rpopredisflag(string rediskey) else

}/**

* 快取中增加flag

** @param rediskey

*/public void lpushredisflag(string rediskey)

}public class redisservice catch (exception e) finally

} }/**

* 移除並獲取列表最後乙個元素

* @param key

* @return

*/public string rpopredislist(string key) catch (exception e) finally

} return null;

}}

思路2:採用的是redis中string的incr和expire操作。因為redis是單執行緒,所有命令依次執行,所以不會出現多台伺服器同時訪問的情況。

語法:incr key  將 key 中儲存的數字值增一。

redis incr 命令將 key 中儲存的數字值增一。

如果 key 不存在,那麼 key 的值會先被初始化為 0 ,然後再執行 incr 操作。

如果值包含錯誤的型別,或字串型別的值不能表示為數字,那麼返回乙個錯誤。

本操作的值限制在 64 位(bit)有符號數字表示之內。

expire key seconds  為給定 key 設定過期時間。

redis expire 命令用於設定 key 的過期時間。key 過期後將不再可用。

方法:每台伺服器執行批處理之前,先去incr乙個固定key,只有返回值等於1的伺服器才能執行批處理任務,然後將該key值設定過期時間。

比如:

jedis = jedistool.getjedis();

if(jedis.incr(pre_again_redis+batchid)!=1) else

集群定時任務執行多次

處理集群定時任務多次執行新增可能存在重複資料問題 第一種就是下面的方法,利用redis 第二種建立資料庫唯一約束 會執行多次 還有quartz等等 設定失效時間為定時任務結束時間至下次定時任務執行時間之間就行,使用setnx方法設定鎖。public static boolean setstringn...

spring的定時任務被多次執行

在使用spring的定時任務時,定時任務被多次執行。有一下這幾種情況 1.錯誤 2.業務邏輯錯誤 3.spring的多次載入 4.tomcat配置導致容器被初始化兩次 解決問題 1.本專案全部使用註解,不存在多次配置,spring載入多次的問題 2.本地idea測試,只執行一次,所以無 和業務邏輯錯...

spring中定時任務執行多次問題排解

專案涉及到定時任務,用的spring自帶的定時任務 部署到伺服器上,卻發現定時任務執行的結果總是重複一次。剛開始以為是資料本身問題。後檢視日誌,定時任務每次都執行了兩遍。因為執行的時間一樣,除了微妙級別有差異。這類問題,網上也有類似的解答,但不符合我的實際情況。但查詢問題的方向一致 定時任務很可能被...