Spring Boot集成ShedLock分布式定時(shí)任務(wù)的實(shí)現(xiàn)示例
一、ShedLock是什么?
以下是ShedLock鎖提供者,通過外部存儲(chǔ)實(shí)現(xiàn)鎖,由下圖可知外部存儲(chǔ)集成的庫還是很豐富的

本篇教程我們基于JdbcTemplate存儲(chǔ)為例來使用ShedLock鎖。
二、落地實(shí)現(xiàn)
1.1 引入依賴包
shedlock所需依賴包:
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>4.23.0</version>
</dependency>
<!--每個(gè)外部存儲(chǔ)實(shí)例所需依賴包不一樣,這里是jdbc-->
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>4.23.0</version>
</dependency>
JdbcTemplate依賴包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
web工程依賴包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.2 配置數(shù)據(jù)庫連接信息
server:
port: 9999
spring:
datasource:
url: jdbc:mysql://192.168.31.158:3306/testjdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.mysql.cj.jdbc.MysqlDataSource
1.3 創(chuàng)建Mysql數(shù)據(jù)表
# MySQL, MariaDB
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));
# Postgres
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL, lock_until TIMESTAMP NOT NULL,
locked_at TIMESTAMP NOT NULL, locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));
# Oracle
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL, lock_until TIMESTAMP(3) NOT NULL,
locked_at TIMESTAMP(3) NOT NULL, locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));
# MS SQL
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL, lock_until datetime2 NOT NULL,
locked_at datetime2 NOT NULL, locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));
# DB2
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL PRIMARY KEY, lock_until TIMESTAMP NOT NULL,
locked_at TIMESTAMP NOT NULL, locked_by VARCHAR(255) NOT NULL);

1.4 配置LockProvider
/**
* @description: Shedlock集成Jdbc配置類
* @author: DT
* @date: 2021/5/22 0:07
* @version: v1.0
*/
// 標(biāo)識(shí)該類為配置類
@Configuration
// //開啟定時(shí)器
@EnableScheduling
// 開啟定時(shí)任務(wù)鎖,指定一個(gè)默認(rèn)的鎖的時(shí)間30秒
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class ShedlockJdbcConfig {
/**
* 配置鎖的提供者
*/
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(
JdbcTemplateLockProvider.Configuration.builder()
.withJdbcTemplate(new JdbcTemplate(dataSource))
.usingDbTime()
.build()
);
}
}
1.5 創(chuàng)建定時(shí)Job
/**
* @description: 開啟分布式鎖定時(shí)任務(wù)
* @author: DT
* @date: 2021/5/22 0:23
* @version: v1.0
*/
@Component
@CommonsLog
public class TimeTaskJob {
private static Integer count = 1;
// @SchedulerLock的作用是保證當(dāng)前定時(shí)任務(wù)的方法執(zhí)行時(shí)獲得鎖,忽略其他相同任務(wù)的執(zhí)行
// name必須要指定,ShedLock就是根據(jù)這個(gè)name進(jìn)行相同任務(wù)判定的
// name:定時(shí)任務(wù)的名字,就是數(shù)據(jù)庫中的主鍵(name)
// lockAtMostFor:鎖的最大時(shí)間單位為毫秒
// lockAtLeastFor:鎖的最小時(shí)間單位為毫秒
/**
* 任務(wù)1每5秒執(zhí)行一次
* lockAtLeastFor:雖然,定時(shí)任務(wù)是每隔5秒執(zhí)行一次,但是,分布式鎖定義的是:每次任務(wù)要鎖住20秒,20秒是持有鎖的最小時(shí)間,必須等20秒后才釋放鎖,并且確保在20秒鐘內(nèi),該任務(wù)不會(huì)運(yùn)行超過1次;
* lockAtMostFor:鎖最大持有時(shí)間30秒,表示最多鎖定30秒鐘,主要用于防止執(zhí)行任務(wù)的節(jié)點(diǎn)掛掉(即使這個(gè)節(jié)點(diǎn)掛掉,在30秒鐘后,鎖也被釋放),一般將其設(shè)置為明顯大于任務(wù)的最大執(zhí)行時(shí)長;如果任務(wù)運(yùn)行時(shí)間超過該值(即任務(wù)30秒鐘沒有執(zhí)行完),則該任務(wù)可能被重復(fù)執(zhí)行。
*/
@Scheduled(cron = "0/5 * * * * ? ")
@SchedulerLock(name = "testJob1",lockAtLeastFor = "20000", lockAtMostFor = "30000")
public void scheduledTask1() {
log.info(Thread.currentThread().getName() + "->>>任務(wù)1執(zhí)行第:" + (count++) + "次");
}
/**
* 任務(wù)2每5秒執(zhí)行一次
*/
@Scheduled(cron = "0/5 * * * * ? ")
@SchedulerLock(name = "testJob2")
public void scheduledTask2() {
log.info(Thread.currentThread().getName() + "->>>任務(wù)2執(zhí)行第:" + (count++) + "次");
}
}
1.6 主啟動(dòng)類
@SpringBootApplication
public class JdbcApplication {
public static void main(String[] args) {
SpringApplication.run(JdbcApplication.class, args);
}
}
1.7 執(zhí)行成功分析
可以看到兩個(gè)任務(wù)交替執(zhí)行,并且我們的count每次自加1都是有序的。但是這里說明一下ShedLock是單線程執(zhí)行的。

1.8 修改表名
shedLock支持關(guān)系型數(shù)據(jù)庫,以mysql為例,配置mysql以及表名;shedLock默認(rèn)表名為shedlock,可以設(shè)置自定義表名。

總結(jié)
核心思想:通過對(duì)公用的數(shù)據(jù)庫中的某個(gè)表進(jìn)行記錄和加鎖,使得同一時(shí)間點(diǎn)只有第一個(gè)執(zhí)行定時(shí)任務(wù)并成功在數(shù)據(jù)庫表中寫入相應(yīng)記錄的節(jié)點(diǎn)能夠成功執(zhí)行而其他節(jié)點(diǎn)直接跳過該任務(wù)。
以上就是Spring Boot集成ShedLock分布式定時(shí)任務(wù)的實(shí)現(xiàn)示例的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot集成ShedLock分布式定時(shí)任務(wù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot整合ShedLock解決定時(shí)任務(wù)防止重復(fù)執(zhí)行的問題
- SpringBoot集成ShedLock實(shí)現(xiàn)分布式定時(shí)任務(wù)的示例代碼
- SpringBoot集成ShedLock實(shí)現(xiàn)分布式定時(shí)任務(wù)
- SpringBoot集成ShedLock實(shí)現(xiàn)分布式定時(shí)任務(wù)流程詳解
- SpringBoot配置ShedLock分布式定時(shí)任務(wù)
- Spring Boot 整合 ShedLock 處理定時(shí)任務(wù)重復(fù)執(zhí)行的問題小結(jié)
相關(guān)文章
Java請(qǐng)求Http接口OkHttp超詳細(xì)講解(附帶工具類)
這篇文章主要給大家介紹了關(guān)于Java請(qǐng)求Http接口OkHttp超詳細(xì)講解的相關(guān)資料,OkHttp是一款優(yōu)秀的HTTP客戶端框架,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
springboot執(zhí)行延時(shí)任務(wù)之DelayQueue的使用詳解
DelayQueue是一個(gè)無界阻塞隊(duì)列,只有在延遲期滿時(shí),才能從中提取元素。這篇文章主要介紹了springboot執(zhí)行延時(shí)任務(wù)-DelayQueue的使用,需要的朋友可以參考下2019-12-12
淺談hashmap為什么查詢時(shí)間復(fù)雜度為O(1)
這篇文章主要介紹了hashmap為什么查詢時(shí)間復(fù)雜度為O(1),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
Java獲取此次請(qǐng)求URL以及服務(wù)器根路徑的方法
這篇文章主要介紹了Java獲取此次請(qǐng)求URL以及服務(wù)器根路徑的方法,需要的朋友可以參考下2015-08-08

