ShedLock锁

ShedLock是一个锁,官方解释是他永远只是一个锁,并非是一个分布式任务调度器。一般shedLock被使用的场景是,你有个任务,你只希望他在单个节点执行,而不希望他并行执行,而且这个任务是支持重复执行的。如对某些查询出来的数据打标签,没有任何的事务性处理操作。以上,官方的解释比较拗口,具体可以参见github上的wiki。

我的理解,ShedLock是一个悲观锁,而无论悲观锁还是乐观锁,他的实现,必须借助于公共存储。
在这里插入图片描述
所以,对于shedLock,需要实现分布式锁,他也需要借助于共享存储,目前支持如下几种方式:

在这里插入图片描述
所以,这个和zookeeper或者redis的理论基本类似。只是这个shedLock封装的更好,不需要我们去实现过多的客户端。而像zookeeper或者redis,需要我们自己实现。具体可以看我之前写的那篇《任务调度总结》文章。还有我github或者码云上的sample。

shedLock支持注解,和spring结合使用更简单。我们来看看他的使用方式。我们以共享存储使用mysql为例子:
首先,需要在你的项目中引入两个包,假设项目是maven构建:

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

其次,在你的启动类中增加注解支持。

@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")

稍后会说明下,这个lockatMostFor的含义。

下一步,需要初始化Provider支持。操作数据库。

@Configuration
public class LockProviderConfiuration {

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

这里全局datasource需要事先创建好。在这里可以直接注入使用。然后实例化jdbcTemplateLockProvider。

建表

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

相信看到这里大家都明白了,name是全局唯一的。用这个来标识全局唯一的定时任务。用此来变相实现一个悲观锁。

以上做好了后,可以开始写你的定时任务了,我们这里写一个测试类

@Component
public class RiskAdminScheduler {

    private static final String SIXTY_MIN = "PT60M";
    private static final String THREE_MIN = "PT3M";

    @Scheduled(cron = "0 */1 * * * ? ")
    @SchedulerLock(name = "test",lockAtLeastForString = THREE_MIN,lockAtMostForString = SIXTY_MIN)
    public void test() {
        System.out.println(LocalDateTime.now());
        System.out.println(Thread.currentThread().getName()+"--executed......");
    }
}

意思就是,当节点挂掉后,这个锁还是要释放的。最长时间就是most设置的,和zookeeper中的临时节点相似,和redis设置超时时间类似。而为了防止集群启动的先后或者各节点 没有做时钟同步,用了least来防止这种情况下,重复起任务的状况。
  这里需要注意的是,least时间设置了后,比如我这里是1分钟定时任务执行一次,而least设置是2分钟。那么也就是2分钟是持有锁的最小时间,2分钟后才释放。所以1分钟执行完的定时任务,必须等到2分钟结束,锁释放后,才能再次执行。当然,实际我们业务中不会出现这种每分钟执行的业务相关的定时任务,即使有,那么情况也比较,比如快速掉单查询,以前做支付的时候,那也是支持并发的,不需要分布式锁的。这里提醒下大家注意下使用场景。大部分场景我们还是可以用这个shedlock的。
  我们看下表中的数据:
在这里插入图片描述
很明显,持有时间是21:06,释放时间是21:09,就是least设置的时间。大家使用的时候注意下。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值