spring-boot 分布式定时任务锁shedlock

先做翻译:

shedlock github地址

shedlock只做一件事,就是确保计划任务最多同时执行一次;如果正在一个节点上执行任务,它将获取一个锁,以防止从另一个节点(或线程)执行相同任务。请注意,过去一个任务已在一个节点上执行,则其他节点上的执行不会等待,只会跳过它;

          目前支持Mongo、JDBC数据库、redis、hazelcast或zookeeper协调的spring scheduled task。

           shedlock不是分布式调度框架,它是只是一个锁!!

用法(仅试了jdbcTemplate)

要求:java8、slf4j-api(官网说的)、spring框架(可选);

当然用shedlock就是为了用它锁 spring自带的 @Scheduled;

pom:

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

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

 

 

1.@SchedulerLock注解:为方法加上锁;name属性(锁的名称)必须指定,每次只能执行一个具有相同名字的任务。

2.lockAtMostFor属性,指定执行节点死亡时应该保留锁的时间。这只是后备,正常情况下,锁定会在任务完成后立即释放。

还是不太理解这个属性的作用;有懂的人可以留言~

明白了: 设置锁的最大持有时间,为了解决如果持有锁的节点挂了,无法释放锁,其他节点无法进行下一次任务。

设置了最大持有持有时间,当持有时间到了自动释放锁,不影响下一次执行;

其实就是设置锁的归还时间。

3.lockAtLeastFor属性,指定保留锁的最短时间。主要目的是在任务非常短的且节点之间存在时钟差异的情况下防止多个节点执行。这个属性是锁的持有时间。设置了多少就一定会持有多长时间,再次期间,下一次任务执行时,其他节点包括它本身是不会执行任务的。

例如:

假设您有一个每15分钟执行一次的任务,通常需要几分钟才能运行。此外,您希望每15分钟最多执行一次。在这种情况下,您可以像这样配置它

import net.javacrumbs.shedlock.core.SchedulerLock;

...
private static final int FOURTEEN_MIN = 14 * 60 * 1000;
...

@Scheduled(cron = "0 */15 * * * *")
@SchedulerLock(name = "scheduledTaskName", lockAtMostFor = FOURTEEN_MIN, lockAtLeastFor = FOURTEEN_MIN)
public void scheduledTask() {
   // do something
}

官网原话如下:

通过设置lockAtMostFor我们确保即使节点死亡也释放锁定,并通过设置lockAtLeastFor 确保它在十五分钟内不会执行多次。请注意,这lockAtMostFor只是执行任务的节点死亡的情况下的安全网,因此将其设置为远远大于最大估计执行时间的时间。 如果任务需要的时间超过lockAtMostFor,则会再次执行。

 我的理解:

设置每15分钟执行一次;

localAtLeastFor=14分钟,就是说当前节点执行时,就会持有锁14分钟,源码默认给了0分钟;

lockAtMostFor默认给了一小时;

别人的理解:

个人理解,拿JDBCTemplate进行说明,就是当第一个微服务执行定时任务的时候,会将此定时任务进行锁操作,然后其他的定时任务就不会再执行,锁操作有一定的时长,超过这个时长以后,再一次,所有的定时任务进行争抢下一个定时任务的执行权利,如此循环。其中两个配置lockAtMostFor和lockAtLeastFor,保证了在一个定时任务的区间内只有一个定时任务在执行,同时也保证了即便是其中的一个定时任务挂掉了,到一定的时间以后,锁也会释放,其他的定时任务依旧会进行执行权的争夺,执行定时任务。

配置任务计划程序

现在我们需要将库集成到Spring中。它是通过包装标准的Spring任务调度程序完成的。

@Configuration
@EnableScheduling
public class ShedlockConfig {

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

    @Bean
    public ScheduledLockConfiguration scheduledLockConfiguration(LockProvider lockProvider) {
        return ScheduledLockConfigurationBuilder
                .withLockProvider(lockProvider)
                .withPoolSize(10)
                .withDefaultLockAtMostFor(Duration.ofMinutes(10))
                .build();
    }
}

自己手动创建库表,默认库表是这样,也可以自定义(未试);

CREATE TABLE shedlock(
    name VARCHAR(64), 
    lock_until TIMESTAMP(3) NULL, 
    locked_at TIMESTAMP(3) NULL, 
    locked_by  VARCHAR(255), 
    PRIMARY KEY (name)
) 
展开阅读全文

没有更多推荐了,返回首页