实现分布式锁SchedulerLock

这篇博客介绍了如何在Spring应用中利用ShedLock实现分布式锁SchedulerLock,以解决多实例任务调度同步问题。文章详细讲解了添加Maven依赖、配置数据库、创建配置类以及创建任务的步骤,并提供了具体的配置代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring 提供了一种简单的方法来实现用于调度作业的 API。在我们部署应用程序的多个实例之前,它运行良好。

默认情况下,Spring 无法处理多个实例上的调度程序同步。它在每个节点上同时执行作业。

1.添加Maven依赖项

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-spring</artifactId>
    <version>2.2.0</version>
</dependency>

2.配置数据库

目前,ShedLock支持Mongo,Redis,Hazelcast,ZooKeeper以及任何带有JDBC驱动程序的内容。

接下来,我们需要为 ShedLock 创建一个数据库表,以保存有关调度程序锁的信息:

CREATE TABLE shedlock (
  name VARCHAR(64),
  lock_until TIMESTAMP(3) NULL,
  locked_at TIMESTAMP(3) NULL,
  locked_by VARCHAR(255),
  PRIMARY KEY (name)
)

3.添加配置类

首先我们需要添加jdbc的包

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-jdbc-template</artifactId>
    <version>2.1.0</version>
</dependency>

然后我们需要创建配置类

让我们使用数据源配置来配置 LockProvider

@Configuration
public class SchedulerConfiguration {
    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
        return new JdbcTemplateLockProvider(dataSource);
    }
}

我们必须提供的其他配置要求是 Spring 配置类的@EnableScheduling@EnableSchedulerLock注释:

@SpringBootApplication
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringApplication.class, args);
    }
}

defaultLockAtMostFor 参数指定在执行节点死亡时应保留锁的默认时间量。它使用 ISO8601 持续时间格式。

4. 创建任务

要创建由 ShedLock 处理的计划任务,我们只需将@Scheduled@SchedulerLock注释放在一个方法上:

创建全局常量类

/**
 * @author wangli
 * @create 2022-11-07 15:02
 */
public class SchedulerConstants {
    /**
     * 持有锁最短时间
     * 该属性指应保留锁定的最短时间。其主要目的是在任务很短且节点之间的时钟差的情况下,防止从多个节点执行。
     */
    public static final String LOCK_MINIMUM_TIME= "PT5M";

    /**
     * 保留锁时间
     * 指定在执行节点死亡时应将锁保留多长时间。这只是一个备用选项,在正常情况下,任务完成后立即释放锁定。
     * 使用时必须将其设置lockAtMostFor为比正常执行时间长得多的值。
     * 如果任务花费的时间超过 lockAtMostFor了所导致的行为,则可能无法预测(更多的进程将有效地持有该锁)。
     */
    public static final String HOLD_LOCK_TIME= "PT8M";

    /**
     * 定时任务执行间隔
     */
    public static final String TIME_INTERVAL= "0 0/5 * * * ?";

}

创建定时任务,测试配置是否生效

	@Scheduled(cron = "0 0/1  * * * ?")
	@SchedulerLock(name = "TaskScheduler_test",lockAtLeastFor= "PT1M", lockAtMostFor= "PT1M")
	public void TaskScheduler_test(){
		System.out.println("当前服务执行定时任务时间为 = "+DateUtil.now());
	}

同时创建两个节点测试是否成功如下

首先,我们添加了 lockAtMinimumFor,以便我们可以在方法调用之间留出一些距离。使用“PT5M”意味着此方法将至少保持锁定五分钟。换句话说,这意味着 ShedLock 运行此方法的频率不超过每五分钟一次。

接下来,我们添加了 lockAtMostFor 来指定在执行节点死亡时锁应保留多长时间。使用“PT14M”表示它将被锁定不超过 14 分钟。

在正常情况下,ShedLock 会在任务完成后直接释放锁。现在,我们不必这样做,因为 @EnableSchedulerLock 中提供了默认值,但我们选择在此处覆盖它。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨会停rain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值