Spring ShedLock

小龙 502 2021-10-23

1、简介

ShedLocks是一个分布式定时任务锁,它能在分布式的环境下,确保任务在同一个时刻最多执行一次。比如:同一个服务部署在多台服务器上,这个服务中定义了一个定时任务,那么在任务执行的时候这些服务器上的任务都会执行,这样是不行的,定时任务只需要执行一次就行了。ShedLock的任务就是保证一个任务在一个节点执行时,它将获得一个把锁,这把锁会阻止从另一个节点执行同一任务;大概的意思就是在一个服务集群中,如果有一个节点服务器执行这个定时任务,那么其他节点服务器不会等着,而是直接跳过执行。

ShedLock可以使用Redis、MongoDB、Mysql,Zookeeper或其他外部存储进行协调,就是通过外部存储来实现锁机制。

1.2 用法

  • 启用和配置计划的锁定
  • 注释任务计划
  • 配置锁提供者

2、开发

2.1 依赖

Grable

// https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-spring
implementation group: 'net.javacrumbs.shedlock', name: 'shedlock-spring', version: '4.29.0'

// https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-provider-redis-spring
implementation group: 'net.javacrumbs.shedlock', name: 'shedlock-provider-redis-spring', version: '4.29.0'

// https://mvnrepository.com/artifact/org.apache.commons/commons-pool2
implementation group: 'org.apache.commons', name: 'commons-pool2', version: '2.11.1'

Maven

<!-- https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-spring -->
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-spring</artifactId>
    <version>4.29.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-provider-redis-spring -->
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-redis-spring</artifactId>
    <version>4.29.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.11.1</version>
</dependency>

配送Redis

spring:
  # Redis相关配置
  redis:
    host: localhost # redis地址
    password: ******* # 面膜
    database: 0
    port: 6379
    timeout: 200
    lettuce: #使用Lettuce连接池
      pool:
        max-idle: 100
        max-wait: 1000
        max-active: 20
        min-idle: 10
        time-between-eviction-runs: 2000 # 每两秒回收一次空闲连接

ShedLock配置类

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S") // 强制释放时间,当任务执行超过指定时间,将会强制结束并释放
public class ShedLockConfig {
    @Value("${spring.profiles.active}")
    private String env;

    @Bean
    public LockProvider redisLockProvider(RedisConnectionFactory factory) {
        return new RedisLockProvider(factory,env); // 使用Redis管理锁
    }
}

定时任务类

@Component // 定时任务是一个组件
@Slf4j
public class RstheScheduleTask {
    // @SchedulerLock注解里面对于任务独占锁的时间有两个配置项:
    // lockAtLeastFor:成功执行定时任务时任务节点所能拥有独占锁的最短时间;
    // lockAtMostFor:成功执行定时任务时任务节点所能拥有独占锁的最长时间;
    @Scheduled(cron = "*/5 * * * * ?") // 每15秒执行一次
    @SchedulerLock(name = "rsthe",lockAtLeastFor = "PT10S",lockAtMostFor = "PT15S")
    public void runJobB() throws InterruptedException {
        log.info("【CRON】定时调度任务,{}",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
        TimeUnit.SECONDS.sleep(10); // 休眠五秒
    }
}

执行结果

2021-10-23 21:05:30.009 INFO [] 22716 --- [pool-2-thread-1] com.rsthe.web.task.RstheScheduleTask : 【CRON】定时调度任务,2021-10-23 21:05:30.009
2021-10-23 21:05:45.008 INFO [] 22716 --- [pool-2-thread-1] com.rsthe.web.task.RstheScheduleTask : 【CRON】定时调度任务,2021-10-23 21:05:45.008
2021-10-23 21:06:00.012 INFO [] 22716 --- [pool-2-thread-2] com.rsthe.web.task.RstheScheduleTask : 【CRON】定时调度任务,2021-10-23 21:06:00.012

Redis中的内容

image.png