springboot项目使用shedlock实现定时任务的分布式锁

一、问题描述

在集群模式部署服务是,会出现所有的定时任务在各自的节点处均会执行一遍,针对这种问题,本文采用springboot集成shedlock的解决方案。

二、具体操作步骤

第一步:引入相关的shedlock相关的jar包,由于项目使用的是mysql数据库,所以采用的是jdbc的解决方案。


    net.javacrumbs.shedlock
    shedlock-spring
    4.5.0


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

第二部:在项目中创建SchduleConfig配置文件(路径为springboot启动类能扫描到的包下面)。

package cn.common.project.config;

import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

import javax.sql.DataSource;

/**
 * @Author ysw
 * @Dcscription:配置shedlock,防止分布式部署情况下定时任务重复执行的问题
 * @Date 2020/3/5 0005 11:13
 */
@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor  =  "30m" )
public class SchduleConfig {

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

第三步:注释自己的定时任务类(注意:SchedulerLock注解上的name必须全局唯一)

package cn.common.project.modular.business.job;

import cn.common.project.modular.system.dao.BussinessMsgMapper;
import net.javacrumbs.shedlock.core.LockAssert;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.time.LocalDateTime;

/**
 * @Author ysw
 * @Dcscription:
 * @Date 2020/3/2 0002 20:24
 */
@Configuration
@EnableScheduling
//配置文件读取是否启用此配置
@ConditionalOnProperty(prefix = "scheduling", name = "enabled", havingValue = "true")
public class TransferDateTimer {

    @Autowired
    private BussinessMsgMapper bussinessMsgMapper;

    /**
     * @param
     * @Description:
     * @Author: ysw
     * @Return void
     * @Date: 2020/03/02 20:27
     */
    //每天早上六点执行
    @Scheduled(cron = "0 0 6 * * ?")
    @SchedulerLock(name = "bussinessMsgTimer", lockAtMostFor = "15m", lockAtLeastFor = "15m")
    public void bussinessMsgTimer() {
        LockAssert.assertLocked();
        bussinessMsgMapper.transferApiData();
        System.err.println("执行调用存储过程将通过api接口写入project_api库的数据写入到project_core库中的定时任务时间: " + LocalDateTime.now());
    }


}

第四步:数据库创建shedlock表。

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

第五步:启动项目,执行定时任务会在表中插入数据。

参数解释:

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

ShedLock github地址为:https://github.com/lukas-krecan/ShedLock

你可能感兴趣的:(Java)