Java中实现分布式定时任务的方法

网友投稿 274 2023-02-09

Java中实现分布式定时任务的方法

定时器Scheduler在平时使用比较频繁,在springboot中,配置好@Scheduled和@EnableScheduling之后,定时器就能正常执行,实现定时任务的功能。

但是在这样的情况下:如果开发的服务需要水平部署实现负载均衡,那么定时任务就会同时在多个服务实例上运行,那么一方面,可能由于定时任务的逻辑处理需要访问公共资源从而造成并发问题;另一方面,就算没有并发问题,那么一个同样的任务多个服务实例同时执行,也会造成资源的浪费。因此需要一种机制来保证多个服务实例之间的定时任务正常、合理地执行。

本文以shedlock为例,来实现分布式定时任务的控制。

ShedLock可以保证多个同样的定时任务在多个服务实例之间最多只执行一次,是一个在分布式环境中保证定时任务合理执行的框架,我们可以叫它分布式定时任务锁。

ShedLock的实现原理是采用公共存储实现的锁机制,使得同一时间点只有第一个执行定时任务的服务实例能执行成功,并在公共存储中存储"我正在执行任务,从什么时候(预计)执行到什么时候",其他服务实例执行时如果发现任务正在执行,则直接跳过本次执行,从而保证同一时间一个任务只被执行一次。

ShedLock的公共存储目前支持的有:MonogoDynamoDBJdbcTemplateZooKeeper (using Curator)Redis (using Spring RedisConnectionFactory)Redis (using Jedis)Hazelcast第一步引入依赖

<dependency>

net.javacrumbs.shedlock

shedlock-spring

4.11.1

net.javacrumbs.shedlock

shedlock-provider-jdbc-template

4.11.1

第二步添加配置类

import net.javacrumbs.shedlock.core.LockProvider;

import net.javacrumbs.shedlock.mMwNPRQprovider.jdbctemplate.JdbcTemplateLockProvider;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.Resource;

import javax.sql.DataSource;

import java.util.TimeZone;

/**

* @descrition shedlock配置类

* @since 2021-01-10 22:39

*/

@Configuration

public class ShedLockConfig {

@Resource

private DataSource dataSource;

/**

* @description

* @date 2021/1/10 22:39

*/

@Bean

public LockProvider lockProvider() {

return new JdbcTemplateLockProvider(

JdbcTemplateLockProvider.Configuration.builder()

.withJdbcTemplate(new JdbcTemplate(dataSource))

.withTimeZone(TimeZone.getTimeZone("GMT+8"))

.build()

);

}

}

第三步,添加公共存储,前面我们说过shedlock支持多种公共存储作为锁,本文我们以mysql为例

CREATE TABLE shedlock (

NAME VARCHAR ( 64 ) NOT NULL,

lock_until TIMESTAMP ( 3 ) NOT NULL,

locked_at TIMESTAMP ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ),

locked_by VARCHAR ( 255 ) NOT NULL,

PRIMARY KEY ( NAME )

);

第四步,添加具体任务类

import lombok.extern.slf4j.Slf4j;

import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;

import java.util.Date;

/**

* @author shane

* @date 2021/1/10 23:39

*/

@Slf4j

@Component

public class TestJob {

/**

* @description 每隔1min打印一次

* @date 2021/1/10 23:39

*/

@Scheduled(cron = "0 0/1 * * * ?")

// lockAtMostFor为锁默认持有时间,会覆盖启动类中的默认持有时间

@SchedulerLock(name = "demo", lockAtMostFor = "70m")

public void print() throws InterruptedException {

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式

log.warn("当前时间:"+df.format(new Date()));

}

}

@SpringBootApplication

@MapperScan("com.example.test.mapper")

@EnableScheduling

@EnableSchedulerLock(defaultLockAtMostFor = "10m") // 默认的锁的时间

public class TestApplication {

public static void main(String[] args) {

SpringApplication.run(TestApplication.class, args);

}

}

参考出处:

https://jianshu.com/p/941416645606

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

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring Bean的包扫描的实现方法
下一篇:自己搭建信息聚合(自己搭建信息聚合的软件)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~