SpringBoot 集成 ShedLock 分布式鎖的示例詳解
一:ShedLock 簡介
ShedLock是一個在分布式環(huán)境中使用的定時任務(wù)框架,用于解決在分布式環(huán)境中的多個實例的相同定時任務(wù)在同一時間點重復(fù)執(zhí)行的問題。ShedLock確保計劃的任務(wù)最多同時執(zhí)行一次。如果一個任務(wù)正在一個節(jié)點上執(zhí)行,它會獲得一個鎖,該鎖將阻止從另一個節(jié)點(或線程)執(zhí)行同一任務(wù)。請注意,如果一個任務(wù)已經(jīng)在一個節(jié)點上執(zhí)行,則在其他節(jié)點上的執(zhí)行不會等待,只是將其跳過。。簡單來說,ShedLock本身只做一件事情:保證一個任務(wù)最多同時執(zhí)行一次。所以如官網(wǎng)所說的,ShedLock不是一個分布式調(diào)度器,只是一個鎖!
注意:ShedLock支持Mongo,Redis,Hazelcast,ZooKeeper以及任何帶有JDBC驅(qū)動程序的東西。本例子使用的是基于Redis的方式。之所以不適用基于jdbc存儲的主要原因是考慮到大量數(shù)據(jù)下的數(shù)據(jù)庫壓力的原因,若本身基于jdbc等,可直接參考官網(wǎng)給出的提示:
創(chuàng)建對應(yīng)的表結(jié)構(gòu)。
CREATE TABLE shedlock(
name VARCHAR(64),
lock_until TIMESTAMP(3) NULL,
locked_at TIMESTAMP(3) NULL,
locked_by VARCHAR(255),
PRIMARY KEY (name)
)
二:配置maven 依賴
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-redis-spring</artifactId>
<version>2.3.0</version>
</dependency>
<!--spring2.0集成redis所需common-pool2 -->
<!-- 必須加上,jedis依賴此 若項目中已經(jīng)引入jedis 請忽略此步驟-->
<!-- spring boot 2.0 的操作手冊有標注 大家可以去看看 地址是:https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/ -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
添加jedis 依賴 若項目中已經(jīng)引入jedis 請忽略此步驟
<!--spring2.0集成redis所需common-pool2 -->
<!-- 必須加上,jedis依賴此 若項目中已經(jīng)引入jedis 請忽略此步驟-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
三:SchedulerLock 基于 Redis 的配置
配置 lockProvider 并且開啟 @EnableSchedulerLock 標簽
import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.redis.spring.RedisLockProvider;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
/**
* @Description SchedulerLock 基于 Redis 的配置
* @Author
* @Date 2020/2/22 18:27
**/
@Configuration
//defaultLockAtMostFor 指定在執(zhí)行節(jié)點結(jié)束時應(yīng)保留鎖的默認時間使用ISO8601 Duration格式
//作用就是在被加鎖的節(jié)點掛了時,無法釋放鎖,造成其他節(jié)點無法進行下一任務(wù)
//這里默認55s
//關(guān)于ISO8601 Duration格式用的不到,具體可上網(wǎng)查詢下相關(guān)資料,應(yīng)該就是一套規(guī)范,規(guī)定一些時間表達方式
@EnableSchedulerLock(defaultLockAtMostFor = "PT55S")
public class ShedLockRedisConfig {
@Value("${spring.profiles.active}")
private String env;
@Bean
public LockProvider lockProvider(RedisConnectionFactory connectionFactory) {
//環(huán)境變量 -需要區(qū)分不同環(huán)境避免沖突,如dev環(huán)境和test環(huán)境,兩者都部署時,只有一個實例進行,此時會造成相關(guān)環(huán)境未啟動情況
return new RedisLockProvider(connectionFactory, env);
}
}
四:在啟動類中添加 @EnableScheduling 標簽
注意,要在啟動類上添加 @EnableScheduling ,表明開啟定時器服務(wù)。若不加定時器是不會起效的。
@SpringBootApplication
@EnableScheduling
public class EpidemicMessageApplication {
public static void main(String[] args) {
SpringApplication.run(EpidemicMessageApplication.class, args);
}
}
五:test 測試案例
//區(qū)分服務(wù)
@Value("${server.port}")
private String port;
@Scheduled(cron = "0 */1 * * * ?")
/**
* lockAtLeastForString的作用是為了防止在任務(wù)開始之初由于各個服務(wù)器同名任務(wù)的服務(wù)器時間差,啟動時間差等這些造成的一些問題,有了這個時間設(shè)置后,
* 就可以避免因為上面這些小的時間差造成的一些意外,保證一個線程在搶到鎖后,即便很快執(zhí)行完,也不要立即釋放,留下一個緩沖時間。
* 這樣等多個線程都啟動后,由于任務(wù)已經(jīng)被鎖定,其他沒有獲得鎖的任務(wù)也不會再去搶鎖。注意這里的時間不要設(shè)置幾秒幾分鐘,盡量大些
*lockAtMostForString 這個設(shè)置的作用是為了防止搶到鎖的那個線程,因為一些意外死掉了,而鎖又始終不被釋放。
* 這樣的話,雖然當前執(zhí)行周期雖然失敗了,但以后的執(zhí)行周期如果這里一直不釋放的話,后面就永遠執(zhí)行不到了。
* 它的目的不在于隱藏任務(wù),更重要的是,釋放鎖,并且查找解決問題。
*至于是否帶有string后綴,只是2種表達方式,數(shù)字類型的就是毫秒數(shù),字符串類型的就有自己固定的格式 ,例如:PT30S 30s時間設(shè)置,單位可以是S,M,H
*/
@SchedulerLock(name = "scheduledController_notice", lockAtLeastForString = "PT15M", lockAtMostForString = "PT14M")
public StandardResult notice() {
try {
logger.info(port + "- 執(zhí)行定時器 scheduledController_notice");
return StandardResult.ok();
} catch (Exception e) {
logger.error("異常信息:", e);
return StandardResult.faild("異常信息", e);
}
}
SchedulerLock注解說明
@SchedulerLock注解一共支持五個參數(shù),分別是
name:用來標注一個定時服務(wù)的名字,被用于寫入數(shù)據(jù)庫作為區(qū)分不同服務(wù)的標識,如果有多個同名定時任務(wù)則同一時間點只有一個執(zhí)行成功
lockAtMostFor:成功執(zhí)行任務(wù)的節(jié)點所能擁有獨占鎖的最長時間,單位是毫秒ms
lockAtMostForString:成功執(zhí)行任務(wù)的節(jié)點所能擁有的獨占鎖的最長時間的字符串表達,例如“PT14M”表示為14分鐘,單位可以是S,M,H
lockAtLeastFor:成功執(zhí)行任務(wù)的節(jié)點所能擁有獨占所的最短時間,單位是毫秒ms
lockAtLeastForString:成功執(zhí)行任務(wù)的節(jié)點所能擁有的獨占鎖的最短時間的字符串表達,例如“PT14M”表示為14分鐘,單位可以是S,M,H
到此這篇關(guān)于SpringBoot 集成 ShedLock 分布式鎖的文章就介紹到這了,更多相關(guān)SpringBoot 分布式鎖ShedLock內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA中properties與yml文件的轉(zhuǎn)變方式
文章介紹了如何在IntelliJ IDEA 2021.1.1中安裝和使用ConvertYAMLandPropertiesFile插件進行YAML和Properties文件之間的轉(zhuǎn)換,安裝步驟包括導(dǎo)航到設(shè)置、安裝插件、找到并安裝插件等,插件支持從Properties文件轉(zhuǎn)換為YAML文件,但轉(zhuǎn)換過程中會丟失注釋2024-12-12
spring?@Transactional注解中常用參數(shù)詳解
這篇文章主要介紹了spring?@Transactional注解中常用參數(shù)詳解,事物注解方式:?@Transactional,本文結(jié)合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2024-02-02

