Java中實現(xiàn)分布式定時任務的方法
定時器Scheduler在平時使用比較頻繁,在springboot中,配置好@Scheduled和@EnableScheduling之后,定時器就能正常執(zhí)行,實現(xiàn)定時任務的功能。
但是在這樣的情況下:如果開發(fā)的服務需要水平部署實現(xiàn)負載均衡,那么定時任務就會同時在多個服務實例上運行,那么一方面,可能由于定時任務的邏輯處理需要訪問公共資源從而造成并發(fā)問題;另一方面,就算沒有并發(fā)問題,那么一個同樣的任務多個服務實例同時執(zhí)行,也會造成資源的浪費。因此需要一種機制來保證多個服務實例之間的定時任務正常、合理地執(zhí)行。
本文以shedlock為例,來實現(xiàn)分布式定時任務的控制。
ShedLock可以保證多個同樣的定時任務在多個服務實例之間最多只執(zhí)行一次,是一個在分布式環(huán)境中保證定時任務合理執(zhí)行的框架,我們可以叫它分布式定時任務鎖。
ShedLock的實現(xiàn)原理是采用公共存儲實現(xiàn)的鎖機制,使得同一時間點只有第一個執(zhí)行定時任務的服務實例能執(zhí)行成功,并在公共存儲中存儲"我正在執(zhí)行任務,從什么時候(預計)執(zhí)行到什么時候",其他服務實例執(zhí)行時如果發(fā)現(xiàn)任務正在執(zhí)行,則直接跳過本次執(zhí)行,從而保證同一時間一個任務只被執(zhí)行一次。
ShedLock的公共存儲目前支持的有:MonogoDynamoDBJdbcTemplateZooKeeper (using Curator)Redis (using Spring RedisConnectionFactory)Redis (using Jedis)Hazelcast第一步引入依賴
<!-- shedlock start --> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>4.11.1</version> </dependency> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-jdbc-template</artifactId> <version>4.11.1</version> </dependency> <!-- shedlock end -->
第二步添加配置類
import net.javacrumbs.shedlock.core.LockProvider; import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import javax.annotation.Resource; import javax.sql.DataSource; import java.util.TimeZone; /** * @descrition shedlock配置類 * @since 2021-01-10 22:39 */ @Configuration public class ShedLockConfig { @Resource private DataSource dataSource; /** * @description * @date 2021/1/10 22:39 */ @Bean public LockProvider lockProvider() { return new JdbcTemplateLockProvider( JdbcTemplateLockProvider.Configuration.builder() .withJdbcTemplate(new JdbcTemplate(dataSource)) .withTimeZone(TimeZone.getTimeZone("GMT+8")) .build() ); } }
第三步,添加公共存儲,前面我們說過shedlock支持多種公共存儲作為鎖,本文我們以mysql為例
CREATE TABLE shedlock ( NAME VARCHAR ( 64 ) NOT NULL, lock_until TIMESTAMP ( 3 ) NOT NULL, locked_at TIMESTAMP ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ), locked_by VARCHAR ( 255 ) NOT NULL, PRIMARY KEY ( NAME ) );
第四步,添加具體任務類
import lombok.extern.slf4j.Slf4j; import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.util.Date; /** * @author shane * @date 2021/1/10 23:39 */ @Slf4j @Component public class TestJob { /** * @description 每隔1min打印一次 * @date 2021/1/10 23:39 */ @Scheduled(cron = "0 0/1 * * * ?") // lockAtMostFor為鎖默認持有時間,會覆蓋啟動類中的默認持有時間 @SchedulerLock(name = "demo", lockAtMostFor = "70m") public void print() throws InterruptedException { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設置日期格式 log.warn("當前時間:"+df.format(new Date())); } }
接著,我們復制一份代碼,分別啟動兩個實例來看結(jié)果數(shù)據(jù)庫記錄
@SchedulerLock注解參數(shù)說明name:定時任務的名字,就是數(shù)據(jù)庫中的內(nèi)個主鍵
lockAtMostFor:鎖的最大時間單位為毫秒
lockAtLeastFor:鎖的最小時間單位為毫秒
對了,還有啟動類的配置
@SpringBootApplication @MapperScan("com.example.test.mapper") @EnableScheduling @EnableSchedulerLock(defaultLockAtMostFor = "10m") // 默認的鎖的時間 public class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } }
參考出處:
https://www.jianshu.com/p/941416645606
shedlock的github地址:https://github.com/lukas-krecan/ShedLock
到此這篇關于Java中實現(xiàn)分布式定時任務的方法的文章就介紹到這了,更多相關java分布式定時任務內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring Security賬戶與密碼驗證實現(xiàn)過程
這篇文章主要介紹了Spring Security賬戶與密碼驗證實現(xiàn)過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2023-03-03Java單線程程序?qū)崿F(xiàn)實現(xiàn)簡單聊天功能
這篇文章主要介紹了Java單線程程序?qū)崿F(xiàn)實現(xiàn)簡單聊天功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10java int轉(zhuǎn)byte和long轉(zhuǎn)byte的方法
下面小編就為大家?guī)硪黄猨ava int轉(zhuǎn)byte和long轉(zhuǎn)byte的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10Spring Security LDAP實現(xiàn)身份驗證的項目實踐
在本文中,我們涵蓋了“使用 Spring Boot 的 Spring Security LDAP 身份驗證示例”的所有理論和示例部分,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-08-08java根據(jù)擴展名獲取系統(tǒng)圖標和文件圖標示例
這篇文章主要介紹了java根據(jù)擴展名獲取系統(tǒng)圖標和文件圖標示例,需要的朋友可以參考下2014-03-03深入理解Mybatis中的resultType和resultMap
這篇文章給大家介紹了mybatis中的resultType和resultMap的用法實例講解,MyBatis中在查詢進行select映射的時候,返回類型可以用resultType,也可以用resultMap,至于兩種用法區(qū)別,通過本文一起學習吧2016-09-09