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

 更新时间:2021年01月11日 08:26:15   作者:只学一点java  
这篇文章主要介绍了Java中实现分布式定时任务,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

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

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

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

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

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

<!-- shedlock start -->
    <dependency>
      <groupId>net.javacrumbs.shedlock</groupId>
      <artifactId>shedlock-spring</artifactId>
      <version>4.11.1</version>
    </dependency>

    <dependency>
      <groupId>net.javacrumbs.shedlock</groupId>
      <artifactId>shedlock-provider-jdbc-template</artifactId>
      <version>4.11.1</version>
    </dependency>
<!-- shedlock end -->

第二步添加配置类

import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.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()));
  }
}

接着,我们复制一份代码,分别启动两个实例来看结果数据库记录@SchedulerLock注解参数说明name:定时任务的名字,就是数据库中的内个主键
lockAtMostFor:锁的最大时间单位为毫秒
lockAtLeastFor:锁的最小时间单位为毫秒

对了,还有启动类的配置

@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://www.jianshu.com/p/941416645606

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

到此这篇关于Java中实现分布式定时任务的方法的文章就介绍到这了,更多相关java分布式定时任务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springcloud 熔断器Hystrix的具体使用

    springcloud 熔断器Hystrix的具体使用

    本篇文章主要介绍了springcloud 熔断器Hystrix的具体使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • JVM调优实战

    JVM调优实战

    本文主要介绍了JVM调优实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • Java 实战范例之线上新闻平台系统的实现

    Java 实战范例之线上新闻平台系统的实现

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+jsp+jdbc+mysql实现一个线上新闻平台系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • JDBC之PreparedStatement类中预编译的综合应用解析

    JDBC之PreparedStatement类中预编译的综合应用解析

    SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句
    2013-07-07
  • RocketMQ特性Broker存储事务消息实现

    RocketMQ特性Broker存储事务消息实现

    这篇文章主要为大家介绍了RocketMQ特性Broker存储事务消息实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Java设置token有效期的5个应用场景(双token实现)

    Java设置token有效期的5个应用场景(双token实现)

    Token最常见的应用场景之一就是身份验证,本文主要介绍了Java设置token有效期的5个应用场景(双token实现),具有一定的参考价值,感兴趣的可以来了解一下
    2024-04-04
  • spring cloud eureka 服务启动失败的原因分析及解决方法

    spring cloud eureka 服务启动失败的原因分析及解决方法

    这篇文章主要介绍了spring cloud eureka 服务启动失败的原因解析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • Springboot如何使用Aspectj实现AOP面向切面编程

    Springboot如何使用Aspectj实现AOP面向切面编程

    这篇文章主要介绍了Springboot如何使用Aspectj实现AOP面向切面编程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 详细谈谈Java中long和double的原子性

    详细谈谈Java中long和double的原子性

    原子性是指一个操作或多个操作要么全部执行,且执行的过程不会被任何因素打断,要么就都不执行,下面这篇文章主要给大家介绍了关于Java中long和double原子性的相关资料,需要的朋友可以参考下
    2021-08-08
  • java中使用@Transactional会有哪些坑

    java中使用@Transactional会有哪些坑

    在Java中,@Transactional是一个常用的注解,用于声明方法应该在一个事务的上下文中执行,本文主要介绍了java中使用@Transactional会有哪些坑,感兴趣的可以了解一下
    2024-04-04

最新评论