任务调度(2)- Spring搭配Shedlock实现分布式定时任务锁

任务调度(2)- Spring搭配Shedlock实现分布式定时任务锁,第1张

任务调度(2)- Spring搭配Shedlock实现分布式定时任务锁

在Spring中,配置@EnableScheduling和@Scheduled之后,就能实现定时任务的功能(任务调度(1)-Spring @Scheduled详解 - 掘金 (juejin.cn))。

但是现在的服务实例一般都是部署多个实例,也就是具有水平扩展的能力。如果多个服务实例都在运行定时任务,会产生

    资源的浪费定时任务的重复执行

所以需要一种机制来保障多个服务实例之间的定时任务正常、合理地运行。

Shedlock

ShedLock(lukas-krecan/ShedLock: Distributed lock for your scheduled tasks (github.com))的出现就是为了解决上述问题,它可以确保你的计划任务在同一时间最多执行一次。如果一个任务正在一个节点上执行,它就会获得一个锁,防止另一个节点(或线程)执行相同的任务。如果一个任务已经在一个节点上执行,其他节点上的执行不会等待,只是被跳过。

ShedLock使用外部存储,如下所示:

Lock Providers

JdbcTemplateR2DBCMicronaut Data JdbcMongoDynamoDBDynamoDB 2ZooKeeper (using Curator)Redis (using Spring RedisConnectionFactory)Redis (using Jedis)HazelcastCouchbaseElasticSearchCosmosDBCassandraConsulArangoDBNeo4jEtcdApache IgniteMulti-tenancyIn-Memory

ShedLock不是一个分布式调度器。请注意,ShedLock不是也永远不会是成熟的调度器,它只是一个锁而已

ShedLock被设计用于这样的情况:你的调度任务还没有准备好被并行执行,但可以安全地重复执行

此外,锁是基于时间的,ShedLock假定节点上的时钟是同步的。

与Spring的结合 1 创建数据库和表
CREATE TABLE `shedlock` (
  `name` varchar(64) NOT NULL,
  `lock_until` timestamp(3) NULL DEFAULT NULL,
  `locked_at` timestamp(3) NULL DEFAULT NULL,
  `locked_by` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
2 引入依赖(这里使用MySQL作为外部锁)
    
        net.javacrumbs.shedlock
        shedlock-spring
    

    
        net.javacrumbs.shedlock
        shedlock-provider-jdbc-template
    

    
        mysql
        mysql-connector-java
    
3 配置文件
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/shedlock?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
    username: xxx
    password: xxx
    type: com.mysql.cj.jdbc.MysqlDataSource
4 启动类添加注解
@SpringBootApplication
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class ShedlockMain {
    public static void main(String[] args) {
        // ...
    }
}
5 提供provider
@Configuration
public class SchedulerConfiguration {
    
    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
        return new JdbcTemplateLockProvider(JdbcTemplateLockProvider.Configuration.builder().withJdbcTemplate(new JdbcTemplate(dataSource)).build()
        );
    }
}
6 实际运行定时任务的代码
@Component
public class TaskScheduler {
    @Scheduled(cron = "0/10 * * * * ?")
    @SchedulerLock(name = "task",
            lockAtLeastFor = "2000", lockAtMostFor = "5000")
    public void scheduledTask() {
        // ...
    }
}

通过如上配置,就可以很简单的与Spring提供的调度进行结合,实现分布式锁。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5710232.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存