【业务功能篇17】Springboot +shedlock锁 实现定时任务

news2024/11/26 4:44:21

业务场景:我们在业务开发过程时,有时需要用到一些定时功能,定期的执行一些数据处理,比如每天固定时间去执行数据,判断是否有符合逻辑的情况,就生成一个告警单,提供给业务查看。

这里接着上一篇技术帖 继续补充定时任务的设计开发  【业务功能篇16】Springboot+mybatisplus+ShedLock框架根据一定的逻辑数据处理规则,定时任务生成告警单

 

Shedlock是个分布式锁,大致实现,就是针对多个服务,提供一个公有的存储,来维护这个锁(类似悲观锁机制)官方解释是他永远只是一个锁,并非是一个分布式任务调度器。一般shedLock被使用的场景是,你有个任务,你只希望他在单个节点执行,而不希望他并行执行,而且这个任务是支持重复执行的。

        ShedLock的作用,确保任务在同一时刻最多执行一次。如果一个任务正在一个节点上执行,则它将获得一个锁,该锁将阻止从另一个节点(或线程)执行同一任务。如果一个任务已经在一个节点上执行,则在其他节点上的执行不会等待,只需跳过它即可
ShedLock使用Mongo,JDBC数据库,Redis,Hazelcast,ZooKeeper或其他外部存储进行协调,即通过外部存储来实现锁机制。

        当第一个微服务执行定时任务的时候,会定时任务进行锁操作,然后其他的定时任务就不会再执行,锁操作有一定的时长,超过这个时长以后,再一次,所有的定时任务进行争抢下一个定时任务的执行权限,如此循环。保证了即使是其中的一个定时任务挂掉了,到一定的时间以后,锁也会释放,其他的定时任务依旧会进行执行权的争夺,执行定时任务。

        

* 分布式锁,保障多节点部署定时任务只执行一次。
* 本质上是通过对主键进行抢占,因此需要确保数据库中存在shedlock表

 一、配置POM依赖

<!--        分布式定时任务锁-->
        <dependency>
            <groupId>net.javacrumbs.shedlock</groupId>
            <artifactId>shedlock-spring</artifactId>
            <version>4.14.0</version>
        </dependency>
        <dependency>
            <groupId>net.javacrumbs.shedlock</groupId>
            <artifactId>shedlock-provider-jdbc-template</artifactId>
            <version>4.43.0</version>
        </dependency>

二、配置启动类 





import lombok.extern.slf4j.Slf4j;

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

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableScheduling;

@Slf4j
@EnableCaching
@SpringBootApplication(exclude = {
        org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration.class,
        SecurityAutoConfiguration.class,
        DataSourceAutoConfiguration.class
}
)
// 开启定时任务注解
@EnableScheduling
// 开启定时任务锁,默认设置锁最大占用时间为30分钟
@EnableSchedulerLock(defaultLockAtMostFor = "30m")
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

三、创建定时任务配置类



package com.xxx.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.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.TimeZone;

/**
 * 分布式锁,保障多节点部署定时任务只执行一次。
 * 本质上是通过对主键进行抢占,因此需要确保数据库中存在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));
 */
@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "30m")
public class ShedLockConfig {
    @Resource
    DataSource dataSource;

    /**
     * 配置锁的提供者
     */
    @Bean
    public LockProvider lockProvider() {
        return new JdbcTemplateLockProvider(
                JdbcTemplateLockProvider.Configuration.builder()
                        .withJdbcTemplate(new JdbcTemplate(dataSource))
                        .withTableName("shedlock")
                        .withTimeZone(TimeZone.getDefault())
                        .build()
        );
    }
}

 

 四、创建对应的定时任务表

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));

 

五、创建定时任务

 

  • 定时任务类上加入注解  @Component @EnableScheduling 注册bean,开启定时任务
  • 定时方法上加入注解:
  • SchedulerLock  分布式锁对象 name值,会插入shedlock表中的name字段,PT2H表示不超过2个小时的锁
  • Scheduled  定时任务每天 早上9点执行一次

    @SchedulerLock(name = "keyword_warning", lockAtLeastFor = "PT2H", lockAtMostFor = "PT2H")
    @Scheduled(cron = "0 0 09 * * ?")

package com.xxx.task;

import com.xxx.ProdMesKeywordWarnRuleService;
import com.xxx.utils.SpringBeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 告警单预警
 */
@Component
@EnableScheduling
@Slf4j
public class ProdMesKeywordWarnSchedule {
    @Resource
    private ProdMesKeywordWarnRuleService warnService;

    @SchedulerLock(name = "keyword_warning", lockAtLeastFor = "PT2H", lockAtMostFor = "PT2H")
    @Scheduled(cron = "0 0 09 * * ?")
    public void createPreWarning() {
        if (!SpringBeanUtils.isTestProfile()) {
            //非测试环境时,运行告警单生成的方法
            warnService.createPreWarningPeriodically();
            warnService.sendMsOnTen();
        }
    }
}

六、定时任务的参数配置:

SchedulerLock 参数

  • @SchedulerLock
    只有带注释的方法被锁定,库忽略所有其他计划的任务。您还必须指定锁的名称。同一时间只能执行一个任务。
  • name
    分布式锁名称,注意 锁名称必须唯一。
  • lockAtMostFor & lockAtMostForString
    指定在执行节点死亡时应将锁保留多长时间。这只是一个备用选项,在正常情况下,任务完成后立即释放锁定。 您必须将其设置lockAtMostFor为比正常执行时间长得多的值。如果任务花费的时间超过 lockAtMostFor了所导致的行为,则可能无法预测(更多的进程将有效地持有该锁)。
    lockAtMostFor 单位 毫秒
    lockAtMostForString 使用“ PT14M” 意味着它将被锁定不超过14分钟。
  • lockAtLeastFor & lockAtLeastForString
    该属性指定应保留锁定的最短时间。其主要目的是在任务很短且节点之间的时钟差的情况下,防止从多个节点执行。

ShedLock支持两种模式的Spring集成,分别是 预定方法代理、TaskScheduler代理。我们默认选择最简单也是最实用的方式:预定方法代理(即 @SchedulerLock 的形式),ShedLock会围绕每个带有@SchedulerLock注释的方法创建AOP代理。这种方法的主要优点是它不依赖于Spring调度。缺点是即使直接调用该方法也会应用锁定。还应注意,当前仅支持返回void的方法,如果您注释并调用具有非void返回类型的方法,则会引发异常。

Scheduled参数 cron定时写法

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;



@Component
public class Jobs {
    //表示方法执行完成后5秒
    @Scheduled(fixedDelay = 5000)
    public void fixedDelayJob() throws InterruptedException {
        System.out.println("fixedDelay 每隔5秒" + new Date());
    }

    //表示每隔3秒
    @Scheduled(fixedRate = 3000)
    public void fixedRateJob() {

        System.out.println("fixedRate 每隔3秒" + new Date());
    }

    //表示每天8时30分0秒执行
    @Scheduled(cron = "0 0,30 0,8 ? * ? ")
    public void cronJob() {
        System.out.println(new Date() + " ...>>cron....");
    }
}

 

  • cron表达式:比如你要设置每天什么时候执行,就可以用它
    cron表达式,有专门的语法,而且感觉有点绕人,不过简单来说,大家记住一些常用的用法即可,特殊的语法可以单独去查。
    cron一共有7位,但是最后一位是年,可以留空,所以我们可以写6位
  • * 第一位,表示秒,取值0-59
    * 第二位,表示分,取值0-59
    * 第三位,表示小时,取值0-23
    * 第四位,日期天/日,取值1-31
    * 第五位,日期月份,取值1-12
    * 第六位,星期,取值1-7,星期一,星期二...,注:不是第1周,第二周的意思
              另外:1表示星期天,2表示星期一。
    * 第7为,年份,可以留空,取值1970-2099
     
  •  (*)星号:可以理解为每的意思,每秒,每分,每天,每月,每年...
  • (?)问号:问号只能出现在日期和星期这两个位置。
  • (-)减号:表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12
  • (,)逗号:表达一个列表值,如在星期字段中使用“1,2,4”,则表示星期一,星期二,星期四
  • (/)斜杠:如:x/y,x是开始值,y是步长,比如在第一位(秒) 0/15就是,从0秒开始,每15秒,最后就是0,15,30,45,60    另:*/y,等同于0/y
  •  0 0 3 * * ?     每天3点执行
  • 0 5 3 * * ?     每天3点5分执行
  • 0 5 3 ? * *     每天3点5分执行,与上面作用相同
  • 0 5/10 3 * * ?  每天3点的 5分,15分,25分,35分,45分,55分这几个时间点执行
  • 0 10 3 ? * 1    每周星期天,3点10分 执行,注:1表示星期天    
  • 0 10 3 ? * 1#3  每个月的第三个星期,星期天 执行,#号只能出现在星期的位置

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/616187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

async函数用法

目录 1.概念 2.本质 3.语法 4.特点 5.async基本使用 6.async里的await普通函数返回值 7.async里的await Promise函数成功返回值 8.async里的await Promise函数失败返回值 9.解决async里的await Promise函数失败后不执行下面内容 1.概念 真正意义上解决异步回调的问题&am…

okta/sf平台实现saml2.0单点登录集成实战(详细步骤+完整代码)

目录 第一步&#xff1a;注册okta账号 第二步&#xff1a;配置okta应用信息 第三步&#xff1a;下载Idp.xml文件 第四步&#xff1a;okta特定配置 第五步&#xff1a;集成测试 基于SuccessFactors的单点登录实现 Github工程代码链接 小结 笔者以前写过一篇关于saml2.0单…

Barra模型因子的构建及应用系列六之Book-to-Price因子

一、摘要 在前期的Barra模型系列文章中&#xff0c;我们构建了Size因子、Beta因子、Momentum因子、Residual Volatility因子和NonLinear Size因子&#xff0c;并分别创建了对应的单因子策略&#xff0c;其中Size因子和NonLinear Siz因子具有很强的收益能力。本节文章将在该系列…

AI 协助办公 |记一次用 GPT-4 写一个消息同步 App

GPT-4 最近风头正劲&#xff0c;作为 NebulaGraph 的研发人员的我自然是跟进新技术步伐。恰好&#xff0c;现在有一个将 Slack channel 消息同步到其他 IM 的需求&#xff0c;看看 GPT-4 能不能帮我完成这次的信息同步工具的代码编写工作。 本文记录了我同 GPT 主要的交互过程…

不定积分练习

不定积分练习 在看视频的时候遇到了一道比较有趣的题&#xff0c;在这里给大家分享一下。 题目 计算 ∫ ( 1 x − 1 x ) e x 1 x d x \int(1x-\dfrac 1x)e^{x\frac 1x}dx ∫(1x−x1​)exx1​dx 解&#xff1a; \qquad 原式 ∫ e x 1 x d x ∫ x ( 1 − 1 x 2 ) e x 1…

ESP Certificate Bundle 分享

基本概念 数字签名&#xff1a;是一种将相当于现实世界中的盖章、签字的功能在计算机世界中进行实现的技术。使用数字签名可以识别篡改和伪装&#xff0c;还可以防止否认。 证书&#xff1a;要开车得先靠驾照&#xff0c;驾照上面记有本人的照片、姓名、出生日期等个人信息&a…

【大唐杯学习超快速入门】5G智能网络优化

这里写目录标题 学习--实验背景上下行速率VOLTE掉话率优化时延优化 接入保持特性提升无线接通率切换成功率 附录 数据分析其他几种选项差不多 学习–实验背景 观看视频进行学习&#xff0c;理解该仿真的内涵 使用人工智能代替人工分析&#xff0c;对5G网络进行优化 上下行速率…

Centos Linux 操作系统中配置Gitlab服务器

基本准备 安装常用的工具包 linux根据操作系统的不同&#xff0c;有不同的安装工具&#xff0c;如&#xff0c; 操作系统 格式 工具 Debian .deb apt, apt-cache, apt-get, dpkg Ubuntu .deb apt, apt-cache, apt-get, dpkg CentOS .rpm yum Fedora .rpm dnf …

企业数智底座白皮书:详解数智平台必备的六大能力

在以“升级企业数智化底座”为主题的2023用友BIP技术大会上&#xff0c;用友联合全球权威咨询机构IDC共同发布《建设数字中国 升级数智底座——企业数智化底座白皮书》&#xff0c;在这本数智平台白皮书里详细解读了企业数智平台应该具备的六大基础能力。 当前企业数智化能力进…

一文剖析mlock锁原理

一般用户空间关联的物理页面是按需通过缺页异常的方式分配和调页&#xff0c;当系统物理内存不足时页面回收算法会回收一些最近很少使用的页面&#xff0c;但是有时候我们需要锁住一些物理页面防止其被回收&#xff08;如时间有严格要求的应用&#xff09;&#xff0c;Linux中提…

市面上的智能电表都有多少安的?适用于那些场景?

随着智能化技术的快速发展&#xff0c;智能电表已经成为了家庭和公寓物业配电系统的必备设备之一。智能电表的功率等级通常为10A或15A&#xff0c;具体取决于电表型号和用途。那么&#xff0c;这些功率等级的智能电表适用于哪些场景呢&#xff1f; 首先&#xff0c;10A功率等级…

【实验练习】基于自注意力机制Vision Transformer模型实现人脸朝向识别 (Python实现) 内容原创

题目 人脸识别是一个复杂的模式识别问题&#xff0c;人脸识别是人脸应用研究中非常重要的一步。由于人脸形状不规则、光线和背景条件多样&#xff0c;导致人脸检测精度受限。实际应用中&#xff0c;大量图像和视频源中人脸的位置、朝向、朝向角度都不是固定的&#xff0c;极大…

内网渗透—隧道技术

内网渗透—隧道技术 1. 隧道技术介绍1.1. 内网—隧道技术1.2. 常见的隧道协议1.3. 前置条件1.4. 判断内网的连通性 2. 网络层隧道技术2.1. ICMP隧道技术2.1.1. 常见工具2.1.2. Pingtunnel基础演示2.1.2.1. 下载服务端2.1.2.2. 下载客户端2.1.2.3. 设置CS连接2.1.2.4. 连接测试 …

功能上新|对比分析、Batches数量、函数释义Tips

本篇是继功能上新&#xff5c;内存篇、GPU篇之后&#xff0c;为大家展示更多关于提升浏览UWA GOT Online Overview报告体验的优化项&#xff0c;包括Overview报告的对比分析、Batches数量、函数释义Tips等。这些功能可以让你更快上手对报告的理解&#xff0c;亦或者更好地融入在…

.Net Core 6 WebApi 项目搭建(一、简单搭建)

前言 对于后端开发者最耻辱的是什么&#xff0c;是只会增删改查&#xff0c;只会CV&#xff0c;只会业务代码。没错&#xff0c;我就是被钉在耻辱柱上的一员&#xff0c;3年开发经验&#xff0c;不会搭建框架&#xff0c;只会写业务代码&#xff0c;丢人丢人啊&#xff0c;所以…

【XR】One More Thing:Vision Pro ,7年磨一剑,2023WWDC苹果发布Vision MR

One More Thing&#xff1a;Vision Pro &#xff0c;7年磨一剑&#xff0c;2023WWDC苹果发布Vision MR 1. 苹果MR Vision Pro&#xff1a;1. 专利布局&#xff1a;苹果表示在开发过程中申请了5000多项专利。2. 专属感知计算芯片3. 显示屏系统方面4. 续航方面5. Vision MR 的新框…

MATLAB安装配置MinGW-w64 C++编译器

文章目录 前言一、Mingw安装1、安装教程2、验证 二、MATLAB安装配置MinGW总结 #pic_center 前言 只是为方便学习&#xff0c;不做其他用途 一、Mingw安装 在网上找到的安装一直报错&#xff1a;The file has been downloaded incorrectly 1、安装教程 建议参考博客Mingw快捷安…

C++内存序、屏障和原子操作

文章目录 一、原子类型二、原子操作函数三、内存序1&#xff09;happens-before和synchronizes-with语义2&#xff09;内存序模式 四、标准库函数五、栅栏&#xff08;Barrier&#xff09; 一、原子类型 标准原子类型的备选名和与其相关的 std::atomic<> 特化类&#xf…

探索低代码的新形态(D2C、ChatGPT)

前言 低代码平台的出现&#xff0c;是互联网快速发展的背景下&#xff0c;满足产品快速迭代的实际需求。现在国内外都已经拥有非常多优秀的开源项目&#xff08;如&#xff1a;lowcode-engine&#xff09;和成熟的商业产品&#xff08;如&#xff1a;Mendix 、PowerPlatform&a…

Orillusion次时代 WebGPU 引擎

Orillusion 次时代 WebGPU 引擎 官网: https://www.orillusion.com/ 教程: https://www.orillusion.com/guide/ Orillusion 引擎是一款完全支持 WebGPU 标准的轻量级渲染引擎。基于最新的 Web 图形API标准&#xff0c;我们做了大量的探索和尝试&#xff0c;实现了很多曾经在 We…