Java中實現(xiàn)分布式定時任務(wù)的方法
定時器Scheduler在平時使用比較頻繁,在springboot中,配置好@Scheduled和@EnableScheduling之后,定時器就能正常執(zhí)行,實現(xiàn)定時任務(wù)的功能。
但是在這樣的情況下:如果開發(fā)的服務(wù)需要水平部署實現(xiàn)負載均衡,那么定時任務(wù)就會同時在多個服務(wù)實例上運行,那么一方面,可能由于定時任務(wù)的邏輯處理需要訪問公共資源從而造成并發(fā)問題;另一方面,就算沒有并發(fā)問題,那么一個同樣的任務(wù)多個服務(wù)實例同時執(zhí)行,也會造成資源的浪費。因此需要一種機制來保證多個服務(wù)實例之間的定時任務(wù)正常、合理地執(zhí)行。
本文以shedlock為例,來實現(xiàn)分布式定時任務(wù)的控制。
ShedLock可以保證多個同樣的定時任務(wù)在多個服務(wù)實例之間最多只執(zhí)行一次,是一個在分布式環(huán)境中保證定時任務(wù)合理執(zhí)行的框架,我們可以叫它分布式定時任務(wù)鎖。
ShedLock的實現(xiàn)原理是采用公共存儲實現(xiàn)的鎖機制,使得同一時間點只有第一個執(zhí)行定時任務(wù)的服務(wù)實例能執(zhí)行成功,并在公共存儲中存儲"我正在執(zhí)行任務(wù),從什么時候(預(yù)計)執(zhí)行到什么時候",其他服務(wù)實例執(zhí)行時如果發(fā)現(xiàn)任務(wù)正在執(zhí)行,則直接跳過本次執(zhí)行,從而保證同一時間一個任務(wù)只被執(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 ) );
第四步,添加具體任務(wù)類
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為鎖默認(rèn)持有時間,會覆蓋啟動類中的默認(rèn)持有時間
@SchedulerLock(name = "demo", lockAtMostFor = "70m")
public void print() throws InterruptedException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設(shè)置日期格式
log.warn("當(dāng)前時間:"+df.format(new Date()));
}
}
接著,我們復(fù)制一份代碼,分別啟動兩個實例來看結(jié)果
數(shù)據(jù)庫記錄
@SchedulerLock注解參數(shù)說明name:定時任務(wù)的名字,就是數(shù)據(jù)庫中的內(nèi)個主鍵
lockAtMostFor:鎖的最大時間單位為毫秒
lockAtLeastFor:鎖的最小時間單位為毫秒
對了,還有啟動類的配置
@SpringBootApplication
@MapperScan("com.example.test.mapper")
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "10m") // 默認(rèn)的鎖的時間
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
到此這篇關(guān)于Java中實現(xiàn)分布式定時任務(wù)的方法的文章就介紹到這了,更多相關(guān)java分布式定時任務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Security賬戶與密碼驗證實現(xiàn)過程
這篇文章主要介紹了Spring Security賬戶與密碼驗證實現(xiàn)過程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03
Java單線程程序?qū)崿F(xiàn)實現(xiàn)簡單聊天功能
這篇文章主要介紹了Java單線程程序?qū)崿F(xiàn)實現(xiàn)簡單聊天功能,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10
java int轉(zhuǎn)byte和long轉(zhuǎn)byte的方法
下面小編就為大家?guī)硪黄猨ava int轉(zhuǎn)byte和long轉(zhuǎn)byte的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10
Spring Security LDAP實現(xiàn)身份驗證的項目實踐
在本文中,我們涵蓋了“使用 Spring Boot 的 Spring Security LDAP 身份驗證示例”的所有理論和示例部分,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
java根據(jù)擴展名獲取系統(tǒng)圖標(biāo)和文件圖標(biāo)示例
這篇文章主要介紹了java根據(jù)擴展名獲取系統(tǒng)圖標(biāo)和文件圖標(biāo)示例,需要的朋友可以參考下2014-03-03
深入理解Mybatis中的resultType和resultMap
這篇文章給大家介紹了mybatis中的resultType和resultMap的用法實例講解,MyBatis中在查詢進行select映射的時候,返回類型可以用resultType,也可以用resultMap,至于兩種用法區(qū)別,通過本文一起學(xué)習(xí)吧2016-09-09

