定時器Scheduler在平時使用比較頻繁,在springboot中,配置好@Scheduled和@EnableScheduling之后,定時器就能正常執行,實作定時任務的功能,
但是在這樣的情況下:如果開發的服務需要水平部署實作負載均衡,那么定時任務就會同時在多個服務實體上運行,那么一方面,可能由于定時任務的邏輯處理需要訪問公共資源從而造成并發問題;另一方面,就算沒有并發問題,那么一個同樣的任務多個服務實體同時執行,也會造成資源的浪費,因此需要一種機制來保證多個服務實體之間的定時任務正常、合理地執行,
本文以shedlock為例,來實作分布式定時任務的控制,
ShedLock可以保證多個同樣的定時任務在多個服務實體之間最多只執行一次,是一個在分布式環境中保證定時任務合理執行的框架,我們可以叫它分布式定時任務鎖,
ShedLock的實作原理是采用公共存盤實作的鎖機制,使得同一時間點只有第一個執行定時任務的服務實體能執行成功,并在公共存盤中存盤"我正在執行任務,從什么時候(預計)執行到什么時候",其他服務實體執行時如果發現任務正在執行,則直接跳過本次執行,從而保證同一時間一個任務只被執行一次,
ShedLock的公共存盤目前支持的有:Monogo
DynamoDB
JdbcTemplate
ZooKeeper (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())); } }
接著,我們復制一份代碼,分別啟動兩個實體來看結果
資料庫記錄
@SchedulerLock注解引數說明
name:定時任務的名字,就是資料庫中的內個主鍵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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/247046.html
標籤:Java
上一篇:servlet與tomcat
下一篇:4 大軟體架構,你們公司用哪種?
