• SpringBoot集成ShedLock实现分布式定时锁


    问题描述:

    在集群模式部署服务端时,会出现所有的定时任务在各自的节点处均会执行一遍,这显然不符合实际的开发场景,针对这种问题,本文给出一种springboot集成shedlock的解决方案
    第一步:引入相关包;
    <!-- 负载均衡定时任务执行一次 -->
    <dependency>
       <groupId>net.javacrumbs.shedlock</groupId>
       <artifactId>shedlock-spring</artifactId>
       <version>2.2.1</version>
    </dependency>
    <dependency>
       <groupId>net.javacrumbs.shedlock</groupId>
       <artifactId>shedlock-provider-jdbc-template</artifactId>
       <version>2.2.1</version>
    </dependency>
    注意:因为本公司的项目持久化采用的mysql数据库,所以引入的是JDBC数据库进行协调

    ShedLock还可以使用Mongo,Redis,Hazelcast,ZooKeeper等外部存储进行协调,例如使用redis则引入下面的包(只尝试过jdbc方式):
    <dependency>
        <groupId>net.javacrumbs.shedlock</groupId>
        <artifactId>shedlock-provider-redis-spring</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    针对不同的协调方式,相关的配置信息可参考https://www.jianshu.com/p/9c6791b617a7

    第二步:向数据库中插入表shedlock;

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

    )

    第三步:在application.properties中添加数据库配置信息

    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
    spring.datasource.username=root1
    spring.datasource.password=root1

    第四步:添加配置类

    import net.javacrumbs.shedlock.core.LockProvider;
    import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
    import net.javacrumbs.shedlock.spring.ScheduledLockConfiguration;
    import net.javacrumbs.shedlock.spring.ScheduledLockConfigurationBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.TaskScheduler;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    import javax.sql.DataSource;
    import java.time.Duration;
    
    @Configuration
    @EnableScheduling
    public class ShedlockConfig {
    
        @Bean
        public LockProvider lockProvider(DataSource dataSource) {
            return new JdbcTemplateLockProvider(dataSource);
        }
    
    //    @Bean
    //    public TaskScheduler taskScheduler(){
    //        return new MySpecialTask​​Scheduler();
    //    }
    
        @Bean
        public ScheduledLockConfiguration scheduledLockConfiguration(LockProvider lockProvider) {
            return ScheduledLockConfigurationBuilder
                    .withLockProvider(lockProvider)
                    .withPoolSize(10)
                    .withDefaultLockAtMostFor(Duration.ofMinutes(10))
                    .build();
        }
    }

    第五步:在启动类上添加启动注解,否则SchedulerLock不会生效

    @EnableSchedulerLock(defaultLockAtMostFor = "PT50S")

    第六步:添加@SchedulerLock到定时器业务方法入口

    private static final int TWENTY_NINE_MIN = 29 * 60 * 1000;
    @Scheduled(cron = "0 */30 * * * ?")
    @SchedulerLock(name = "scheduledTask", lockAtMostFor = TWENTY_NINE_MIN, lockAtLeastFor = TWENTY_NINE_MIN)
    public void scheduledTask() {
    //    System.out.println(new Date() + "scheduledTask执行1次");
    }

    参数解释:

    name属性:锁名称,必须指定,每次只能执行一个具有相同名字的任务,锁名称应该是全局唯一的;
    lockAtMostFor属性:设置锁的最大持有时间,为了解决如果持有锁的节点挂了,无法释放锁,其他节点无法进行下一次任务;
    lockAtMostForString属性:成功执行任务的节点所能拥有的独占锁的最长时间的字符串表达,例如“PT14M”表示为14分钟
    lockAtLeastFor属性:指定保留锁的最短时间。主要目的是在任务非常短的且节点之间存在时钟差异的情况下防止多个节点执行。这个属性是锁的持有时间。设置了多少就一定会持有多长时间,再此期间,下一次任务执行时,其他节点包括它本身是不会执行任务的
    lockAtLeastForString属性:成功执行任务的节点所能拥有的独占锁的最短时间的字符串表达,例如“PT14M”表示为14分钟


    原文出处:https://www.cnblogs.com/Iris1998/p/11413099.html

  • 相关阅读:
    会话跟踪之Session
    利用Cookie保存用户身份信息实现免登录
    会话跟踪之Cookie
    JSP的使用
    Servlet的生命周期以及线程安全问题
    将数组转化成递归
    自己配置webpack的vue
    自己配置webpack打包
    echarts堆叠图tooltip中如何仅展示鼠标当前位置相应的指标数据
    富文本编辑器的毛毛雨
  • 原文地址:https://www.cnblogs.com/panchanggui/p/14735044.html
Copyright © 2020-2023  润新知