分布式任务同步:在Spring中利用ShedLock

详细讨论了ShedLock的原理、配置步骤以及在实际项目中的应用场景,为处理复杂的分布式系统任务提供了有力支持。

Spring ShedLock,分布式任务,任务同步,定时任务,多实例同步,并发控制

在当今的分布式计算环境中,协调多个节点之间的任务执行,确保它们在没有冲突或重复的情况下执行,面临着重大挑战。无论是管理周期性任务、批处理过程还是关键系统任务,保持同步和一致性对于无缝运行至关重要。

问题

假设我们需要按计划运行某些任务,无论是数据库清理任务还是某些数据生成任务。如果直接解决这个问题,你可以使用Spring Framework中包含的`@Schedules`注解来解决这个问题。该注解允许您按固定间隔或按cron计划运行代码。但是,如果我们的服务实例数量超过一个怎么办?在这种情况下,任务将在我们的每个服务实例上执行。

ShedLock

ShedLock确保您的定时任务在同一时间最多只执行一次。该库通过外部存储实现锁。如果一个任务在一个实例上执行,锁被设置,所有其他实例不等待,并跳过任务的执行。这实现了“最多执行一次”。外部存储可以是关系型数据库(PostgreSQL、MySQL、Oracle等)通过JDBC工作,NoSQL(Mongo、Redis、DynamoDB)以及许多其他存储(完整列表可以在项目页面上找到)。

让我们以使用PostgreSQL为例。首先,让我们使用Docker启动数据库:

docker run -d -p 5432:5432 --name db \
    -e POSTGRES_USER=admin \
    -e POSTGRES_PASSWORD=password \
    -e POSTGRES_DB=demo \
    postgres:alpine

现在需要创建一个锁表。在项目页面上,我们需要找到针对PostgreSQL的SQL脚本:

CREATE TABLE shedlock(
    name VARCHAR(64) NOT NULL,
    lock_until TIMESTAMP NOT NULL,
    locked_at TIMESTAMP NOT NULL, 
    locked_by VARCHAR(255) NOT NULL, 
    PRIMARY KEY (name)
);

这里:

  • `name` - 锁的唯一标识符,通常表示被锁定的任务或资源

  • `lock_until` - 指示持有锁的结束时间的时间戳

  • `locked_at` - 指示获取锁的时间戳

  • `locked_by` - 获取锁的实体的标识符(例如,应用程序实例)

接下来,创建一个Spring Boot项目并在`build.gradle`中添加必要的依赖项:

implementation 'net.javacrumbs.shedlock:shedlock-spring:5.10.2'
implementation 'net.javacrumbs.shedlock:shedlock-provider-jdbc-template:5.10.2'

现在描述配置:

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "10m")
public class ShedLockConfig {
    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
        return new JdbcTemplateLockProvider(
            JdbcTemplateLockProvider.Configuration.builder()
                    .withJdbcTemplate(new JdbcTemplate(dataSource))
                    .usingDbTime()
                    .build()
        );
    }
}

让我们创建一个`ExampleTask`,每分钟开始一次并执行一些耗时动作。为此,我们将使用`@Scheduled`注解:

@Service
public class ExampleTask {
    
    @Scheduled(cron = "0 * * ? * *")
    @SchedulerLock(name = "exampleTask", lockAtMostFor = "50s", lockAtLeastFor = "20s")
    public void scheduledTask() throws InterruptedException {
        System.out.println("task scheduled!");
        Thread.sleep(15000);
        System.out.println("task executed!");
    }
}

在这里,我们使用`Thread.sleep`模拟任务的执行时间为15秒。一旦应用程序启动并任务执行开始,将在数据库中插入一条记录。

如果同时,另一个应用程序尝试运行任务,它将无法获取锁并跳过任务执行:

2024-02-18 08:08:50.057 DEBUG 45988 --- [   scheduling-1] n.j.s.core.DefaultLockingTaskExecutor    
: Not executing 'exampleTask'. It's locked.

在第一个应用程序获取锁时,会在数据库中创建一条记录,该记录的锁时间等于锁设置中的`lockAtMostFor`。这个时间是必要的,以确保锁不会永远设置,以防应用程序崩溃或由于某种原因终止(例如,在Kubernetes中从一个节点驱逐Pod到另一个节点)。成功执行任务后,应用程序将更新数据库条目,并将锁定时间减少到当前时间,但如果任务执行时间非常短,则此值不能小于配置中的`lockAtLeastFor`。此值有助于最大程度地减少实例之间的时钟不同步。它确保您的定时任务只被同时执行一次。

结论

ShedLock是协调复杂Spring应用程序中任务的有用工具。它确保任务顺利运行且仅运行一次,即使跨多个实例也是如此。它易于设置,并为Spring应用程序提供了可靠的任务处理能力,使其成为处理分布式系统的任何人都很有价值的工具。

项目代码可在GitHub上找到。https://github.com/vshago/shedlock-demo文章来源地址https://www.toymoban.com/diary/apps/714.html

到此这篇关于分布式任务同步:在Spring中利用ShedLock的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

原文地址:https://www.toymoban.com/diary/apps/714.html

如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用
使用Azure DevOps构建发布流水线
上一篇 2024年02月07日 23:45
Spring Boot 3.2: 如何用RestClient替换传统的RestTemplate
下一篇 2024年02月20日 16:59

相关文章

  • java中定时任务 schedule 分布式下没有锁住 时间不同步 执行滞后 相对时间 系统时间 spring springboot

    java.util.Timer计时器可以进行:管理任务延迟执行(“如1000ms后执行任务”),及周期性执行(“如每500ms执行一次该任务”)。 但是,Timer存在一些缺陷,应考虑使用ScheduledThreadPoolExecutor代替,Timer对调度的支持是基于绝对时间,而不是相对时间的,由此任务对系统时钟的改变是敏感

    2024年02月10日
    浏览(36)
  • spring boot + xxl-job 分布式任务调度

    1、任务调度 1.1、什么是任务调度 我们可以先思考一下下面业务场景的解决方案: 某电商系统需要在每天上午10点,下午3点,晚上8点发放一批优惠券。 某财务系统需要在每天上午10点前结算前一天的账单数据,统计汇总。 某电商平台每天凌晨3点,要对订单中的无效订单进行

    2024年02月09日
    浏览(45)
  • Spring Boot 3 整合 xxl-job 实现分布式定时任务调度,结合 Docker 容器化部署(图文指南)

    xxl-job 是一个分布式任务调度平台,它提供了强大的任务调度和执行能力,可以帮助我们实现任务的自动化调度和执行。本文将介绍如何在 Docker 环境下部署 xxl-job,并将其与 Spring Boot 进行整合。 数据库脚本:tables_xxl_job-2.4.0.sql Docker 镜像地址: https://hub.docker.com/r/xuxueli/xxl-jo

    2024年02月06日
    浏览(50)
  • 分布式任务调度,定时任务的处理方案

    适用场景: Spring 定时任务是 Spring 框架提供的一种轻量级的任务调度方案,它的特点是简单易用、轻量级。Spring 定时任务的执行是在 单个节点 上进行的,如果需要分布式任务调度,需要自己实现相应的解决方案。 1.导入依赖版本自己控制 2.启动类加上@EnableScheduling 3.编写业

    2023年04月14日
    浏览(43)
  • 分布式、锁、延时任务

    Redis分布式锁-这一篇全了解(Redission实现分布式锁完美方案) ls / / 下有哪些子节点 get /zookeeper 查看某个子节点内容 create /aa “test” delete /aa set /aa “test01” 模式 默认创建永久 create -e 创建临时 create -e /zz “hello zz” create -s 创建 有序节点 create -s -e 临时序列化节点 一次性的监

    2024年02月09日
    浏览(49)
  • 分布式定时任务

    本文引用了谷粒商城的课程 定时任务是我们系统里面经常要用到的一些功能。如每天的支付订单要与支付宝进行对账操作、每个月定期进行财务汇总、在服务空闲时定时统计当天所有信息数据等。 定时任务有个非常流行的框架Quartz和Java原生API的Timer类。Spring框架也可以支持

    2023年04月15日
    浏览(43)
  • 分布式任务调度系统分析

    首先,我们来思考一些几个业务场景: XX 信用卡中心,每月 28 日凌晨 1:00 到 3:00 需要完成全网用户当月的费用清单的生成 XX 电商平台,需要每天上午 9:00 开始向会员推送送优惠券使用提醒 XX 公司,需要定时执行 Python 脚本,清理掉某文件服务系统中无效的 tmp 文件 最开始,

    2023年04月22日
    浏览(47)
  • 分布式运用——rsync远程同步

    rsync(Remote Sync,远程同步)是由Andrew Tridgell于1996年开发的一款开源软件。 是一个开源的快速备份工具,可以在不同主机之间镜像同步整个目录树,支持增量备份,并保持链接和权限,且采用优化的同步算法,传输前执行压缩,因此非常适用于异地备份、镜像服务器等应用。

    2024年02月12日
    浏览(39)
  • 分布式之任务调度学习二

    Spring-quartz 工程 Spring 在 spring-context-support.jar 中直接提供了对 Quartz 的支持 可以在配置文件中把 JobDetail、Trigger、Scheduler 定义成 Bean。 4.1 定义 Job 4.2 定义 Trigger 4.3 定义 Scheduler 既然可以在配置文件配置,当然也可以用@Bean 注解配置。在配置类上加上@Configuration 让 Spring 读取到

    2024年02月03日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包