java 分布式 定时任务_Java中实现分布式定时任务的方法
定时器Scheduler在平时使用比较频繁,在springboot中,配置好@Scheduled和@EnableScheduling之后,定时器就能正常执行,实现定时任务的功能。
但是在这样的情况下:如果开发的服务需要水平部署实现负载均衡,那么定时任务就会同时在多个服务实例上运行,那么一方面,可能由于定时任务的逻辑处理需要访问公共资源从而造成并发问题;另一方面,就算没有并发问题,那么一个同样的任务多个服务实例同时执行,也会造成资源的浪费。因此需要一种机制来保证多个服务实例之间的定时任务正常、合理地执行。
本文以shedlock为例,来实现分布式定时任务的控制。
ShedLock可以保证多个同样的定时任务在多个服务实例之间最多只执行一次,是一个在分布式环境中保证定时任务合理执行的框架,我们可以叫它分布式定时任务锁。
ShedLock的实现原理是采用公共存储实现的锁机制,使得同一时间点只有第一个执行定时任务的服务实例能执行成功,并在公共存储中存储"我正在执行任务,从什么时候(预计)执行到什么时候",其他服务实例执行时如果发现任务正在执行,则直接跳过本次执行,从而保证同一时间一个任务只被执行一次。
ShedLock的公共存储目前支持的有:MonogoDynamoDBJdbcTemplateZooKeeper (using Curator)Redis (using Spring RedisConnectionFactory)Redis (using Jedis)Hazelcast第一步引入依赖
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.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
到此这篇关于Java中实现分布式定时任务的方法的文章就介绍到这了,更多相关java分布式定时任务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
java 分布式 定时任务_Java中实现分布式定时任务的方法相关推荐
- java 文件通配符_Java中泛型通配符的使用方法示例
本文实例讲述了Java中泛型通配符的使用方法.分享给大家供大家参考,具体如下: 一 点睛 引入通配符可以在泛型实例化时更加灵活地控制,也可以在方法中控制方法的参数. 语法如下: 泛型类名 extend ...
- java thread join()_Java中Thread.join()的使用方法
概要 本文分三个部分对thread.join()进行分析: 1. join() 的示例和作用 2. join() 源码分析 3. 对网上其他分析 join() 的文章提出疑问 1. join() 的示 ...
- java 类型转换方法_Java中的实用类型转换的方法
Java中的实用类型转换的方法 1, 类型转换 JAVA中常用数据类型转换函数 虽然都能在JAVA API中找到,整理一下做个备份. string->byte Byte ...
- java对象数组_Java中对象数组的使用方法详解
本文实例讲述了Java中对象数组的使用方法.分享给大家供大家参考,具体如下: 一 点睛 对象可以用数组来存放,通过下面两个步骤来实现. 1 声明以类为数据类型的数组变量,并用new分配内存空间给数组. ...
- java 数组赋值_java中为数组赋值的方法
java中为数组赋值的方法 发布时间:2020-06-25 14:31:36 来源:亿速云 阅读:184 作者:Leah 这期内容当中小编将会给大家带来有关java中为数组赋值的方法,文章内容丰富且以 ...
- java 随机数生成实现_Java中生成随机数的实现方法总结
搜索热词 在实际开发工作中经常需要用到随机数.如有些系统中创建用户后会给用户一个随机的初始化密码.这个密码由于是随机的,为此往往只有用户自己知道.他们获取了这个随机密码之后,需要马上去系统中更改.这就 ...
- java string 精度_Java 中的浮点数取精度方法
1 packagecn.com.cxsw.utils;2 3 importjava.math.BigDecimal;4 5 /** 6 * 与小数位精度(四舍五入等)相关的一些常用工具方法.7 *8 ...
- java instance关键字_Java中instanceof关键字和isInstance()方法的区别是什么
instanceof关键字和isInstance()方法都用于检查对象的类,那么它们之间有什么区别?下面本篇文章就来带大家了解一下instanceof关键字和isInstance()方法之间的区别,希 ...
- java split 冒号_Java中字符串split() 的使用方法,没你想的那么简单
先看下面的方法,事先预测一下,经过split方法,按逗号进行分割为数组之后,生成的数组的长度是多少,目测很多人都觉得是8,但是结果却出乎意料.是5而不是8. private static void t ...
- java数组赋值_java中给数组赋值的方法
1.数组操作中,可以使用等于(=)赋值 注意:此时新数组只是指向原数组的存储空间,并没有重新申请新的空间. 实例:public class ArrayTest{ public static void ...
最新文章
- 一个框架解决几乎所有机器学习问题
- MySQL5.6开启慢查询
- Objective-C objc_class 介绍
- NodeJS实现TCPSocket(套接字)服务器和客户端
- Android 自定义 圆环,Android自定义view实现圆环效果实例代码
- gson java 对象_Gson把json串转换成java实体对象
- CMake下载及安装
- 新建jsp报错“The superclass javax.servlet.http.HttpServlet was not found on the Java Build Path”...
- 我的程序员之路(4)——工作半年
- 3D打印gcode命令大全及解析
- 计算机主板 华硕 游戏用,DIY电脑的基石,华硕TUF B360M-PLUS GAMING S游戏主板
- html怎么实现网页中文件下载功能
- 别做正常的傻瓜-读后感
- RMAN高级应用_pizi.pdf
- spark报错:java.io.IOException: Filesystem closed
- vs2015调试时无法显示QString变量的值,只显示地址
- rabbitmq(二):死信队列,springboot 实现3种情况
- ACID特性的实现原理与MySQL事务的关系
- 分享自己学英语的经验
- 恒大帝景220平文华东路