SpringBoot2.1.9 分布式锁ShedLock不执行坑

一、起由

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class TimerTaskConfig implements SchedulingConfigurer {

    @Bean
    public LockProvider scheduledLockConfiguration(RedisConnectionFactory redisConn) {
        return new RedisLockProvider(redisConn);
    }

}

SpringBoot Scheduled调度池的线程条数默认为1,多定时任务会积压等待延迟执行。

一下是两种修改方式

(1)@Async注解

@Async注解会异步执行调度任务,避免任务多积压不执行。

也带来了新的问题:任务执行超时没有被分布式锁锁住。

由于任务异步执行,分布式锁代码执行立即返回了,耗费时间几乎为0s,也就是ShedLock配置的lockAtLeastFor生效,lockAtMostFor是永远不生效的。

(2)配置多线程调度池

配置多线程的调度池,可以避免多任务积压,任务执行超时也可以控制。

 

二、配置多线程调度池

从博客网站里查来的调度池配置方式

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class TimerTaskConfig implements SchedulingConfigurer {

    @Bean
    public LockProvider scheduledLockConfiguration(RedisConnectionFactory redisConn) {
        return new RedisLockProvider(redisConn);
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setScheduler(setTaskExecutors());
    }

    @Bean(destroyMethod="shutdown")
    public ScheduledExecutorService setTaskExecutors(){
        return Executors.newScheduledThreadPool(10); // 10个线程来处理。
    }
}

配置后定时任务可以执行,发布到多台机器后,发现所有的机器都在执行相同的定时任务,ShedLock不起作用了。

分析原因:

给scheduledTaskRegistrar注册了一个没有lock的scheduler ScheduledExecutorService,而不是LockableTaskScheduler。

 

三、正确的配置

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class TimerTaskConfig {

    @Bean
    public LockProvider scheduledLockConfiguration(RedisConnectionFactory redisConn) {
        return new RedisLockProvider(redisConn);
    }


    @Bean(destroyMethod="shutdown")
    public ScheduledExecutorService setTaskExecutors(){
        return Executors.newScheduledThreadPool(10); // 10个线程来处理。
    }
}

 

你可能感兴趣的:(Spring,Boot,编程难题)