springboot使用shedlock - 定时任务锁(控制集群定时任务)

POM文件:


        
            net.javacrumbs.shedlock
            shedlock-spring
            3.0.0



        
            net.javacrumbs.shedlock
            shedlock-provider-mongo
            3.0.0

启动类加入注解:

//其他注解省略 ······ PT30S,是30秒的意思
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class Oms2RtocRtdcacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Oms2RtocRtdcacheApplication.class, args);
    }
}

编写配置类:
使用mongodb作为中间表,存储任务信息。它还支持jdbc,redis等等一大堆的数据库用来存储任务信息,这里使用mongodb,配置类需要给它把连接实例放进去,使用其他数据库同理。

import com.mongodb.client.MongoCollection;
import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.mongo.MongoLockProvider;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;

@Configuration
public class ShedLockConfig {
    @Autowired
    private MongoTemplate template;

    @Bean
    public LockProvider lockProvider(){
        MongoCollection mongo = template.getCollection("realtimework");
        return new MongoLockProvider(mongo);
    }
}

定时任务:

//每2秒执行
//name 是定时任务的名字
//lockAtLeastFor 是持有锁的最小时间,单位毫秒
//lockAtMostFor 是持有锁的最大时间,单位毫秒
//@SchedulerLock注解还有两个参数,是最小、最大时间字符串的方式表示
@Scheduled(cron = "*/2 * * * * ?")
@SchedulerLock(name = "dataHouseKeepingLock", lockAtLeastFor = 2000, lockAtMostFor = 2000)
public void test1()throws Exception{
        log.info("定时任务执行" );
}

执行定时任务,mongodb中产生的记录。它保证集群或者分布式部署下,多个节点同时执行定时任务,只有一个节点能生效执行。原理就是通过时间来判断,所以,多个(服务器)节点的时间需要一致。
springboot使用shedlock - 定时任务锁(控制集群定时任务)_第1张图片
可以使用以后,就可以将同一个项目,同样的代码,复制多分,部署到各个节点上了。他们是交错执行的。


以下是采用Redis自己写的控制定时任务的东西,思路参考网络上的文章。原理就是利用本机IP和设置key的失效时间,来辨别节点是否宕机,或定时任务不执行。

/**
     * 自实现redis定时任务控制
     * @param lockName - 锁名称 - 不要重复起名 dataStorage
     * @return
     * @throws Exception
     */
    public static boolean redisLock(String lockName) throws Exception{
        String ip = InetAddress.getLocalHost().getHostAddress();//本机IP
        String currentIp = (String) RedisUtils.get(lockName);
        // 如果为空,说明没有定时任务执行,赋值进去,过期时间2秒
        if(currentIp == null){
            RedisUtils.set(lockName,ip,2);//此处2秒超时,自行设置,根据定时任务周期设置
            return true;
        }
        // 不为空,说明有任务在执行,判断是否是当前机器,是则返回true-继续执行,否则返回false-不执行
        if(currentIp.equals(ip)){
        	RedisUtils.set(lockName,ip,2);
            return true;
        }else{
            return false;
        }
    }

使用:

//每2秒执行 - 获取实时数据
@Scheduled(cron = "*/2 * * * * ?")
public void test1()throws Exception{
        boolean dataStorage = redisLock("dataStorage");
        if(dataStorage){
            log.info("本机执行任务!!!");
        } else {
            log.error("其他机器正在执行任务,本次任务退出,并清空缓存!");
            //此处说明定时任务在其他机器执行,可以进行其他操作后return
            //比如可以清理一些定时任务里需要remove的数据
			//rtd.clear();//清空缓存
        }
    }

你可能感兴趣的:(java)