最新实战案例锦集:《Spring Boot3实战案例合集》持续更新,每天至少更新一篇文章,订阅后将赠送文章最后展示的所有MD文档(学习笔记)。
环境:SpringBoot3.2.5
本篇文章将介绍一款在分布式(多节点)环境下,防止调度任务重复执行的强大组件。
1. 简介
在分布式系统中,任务调度是一个常见的需求,尤其是在需要定期执行某些任务的场景下。然而,如何确保任务在多节点环境中不被重复执行,是一个挑战。
当多个节点同时运行相同的定时任务时,可能会导致任务被多次触发,从而影响系统的正确性和性能。为了解决这个问题,通常我们可以采取以下几种策略:
数据库锁:利用数据库的唯一索引或排他锁来确保同一时间只有一个节点可以执行任务。例如,可以在任务表中插入一条带有唯一键的任务记录,只有成功插入的节点才能执行任务。
分布式锁:使用分布式锁服务(如 Redis 的 SETNX 命令或 ZooKeeper 的临时节点)来控制任务的执行。只有获取到锁的节点才能执行任务,其他节点在等待锁释放后再尝试获取。
任务分配:通过任务调度中心(如 Quartz 集群)来管理和分配任务,确保每个任务只被分配给一个节点执行。调度中心会跟踪任务的状态,防止重复执行。
幂等性设计:设计任务使其具有幂等性,即多次执行任务的效果与一次执行相同。这可以通过记录任务的执行状态或结果来实现,确保即使任务被多次触发也不会产生副作用。
通过这些方法,可以有效地避免多节点环境下调度任务的重复执行问题,保证系统的稳定性和可靠性。
下面我将介绍一个非常不错的组件 ShedLock,该组件能够在分布式场景下解决任务重复调度问题。
ShedLock 可确保计划任务在同一时间最多执行一次。如果一个任务正在一个节点上执行,它就会获得一个锁,阻止另一个节点(或线程)执行同一任务。请注意,如果一个节点上正在执行一个任务,其他节点上的任务执行不会等待,而是直接跳过。
ShedLock 使用外部存储,如 Mongo、JDBC 数据库、Redis、Hazelcast、ZooKeeper 或其他存储。
在某些方面ShedLock可以成为Quartz 的替代品。
由于ShedLock支持的外部存储比较多,我这里只详细的介绍基于JDBC和Redis两种持久化方式。
2. 实战案例
2.1 引入依赖
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>${shedlock.version}</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>${shedlock.version}</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-redis-spring</artifactId>
<version>${shedlock.version}</version>
</dependency>
目前最新版本是5.15.0。该组件的更新速度还是不错的。
引入依赖后,其它没有配置,只需要在程序中开启功能即可。
@EnableSchedulerLock(defaultLockAtMostFor = "10m")
public class App {}