Spring ShedLock is a distributed lock for scheduled tasks. It ensures that only one instance of a scheduled task runs at the same time in a distributed environment, such as a cluster of microservices. This is particularly useful for tasks that should not be executed concurrently, like data processing or cleanup jobs.
How ShedLock Works
Lock Provider: A lock provider is configured to manage the locks. This could be a database, Redis, etc.
Annotations: Tasks are annotated with @SchedulerLock to specify lock names and durations.
Execution: When a task is scheduled to run, ShedLock checks if a lock is available. If it is, the task runs and the lock is held for the specified duration.
Release: After the task completes or the lock duration expires, the lock is released, allowing other instances to acquire it.
Step 1. Add Dependencies
<dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>4.27.0</version> </dependency> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-jdbc-template</artifactId> <version>4.27.0</version> </dependency>
Step 2. Create Configuration Class
Create a configuration class to set up ShedLock with a JDBC lock provider.
package com.kswaughs.batch.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; @Configuration @EnableSchedulerLock(defaultLockAtMostFor = "PT30S") public class ShedLockConfig { @Bean public LockProvider lockProvider(JdbcTemplate jdbcTemplate) { return new JdbcTemplateLockProvider( JdbcTemplateLockProvider.Configuration.builder() .withJdbcTemplate(jdbcTemplate) .usingDbTime() // Works with PostgreSQL, MySQL, MariaDB, MS SQL, Oracle, DB2 .build() ); } }
Step 3: Create Scheduled Task
Create a scheduled task that uses ShedLock to ensure only one instance of the task runs at a time.
package com.kswaughs.batch.job; import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class ScheduledTasks { @Scheduled(cron = "0 0/5 * * * ?") @SchedulerLock(name = "TaskName", lockAtMostFor = "PT10M", lockAtLeastFor = "PT5M") public void performTask() { // Task implementation System.out.println("Scheduled task is running..."); } }
Step 4: Enable Scheduling
Ensure that scheduling is enabled in your Spring Boot application by adding @EnableScheduling to your main application class.
package com.kswaughs.batch; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Step 5: Create Database Table - ShedLock
The ShedLock library does not create the table automatically. You need to create the table manually. Here is the SQL script to create the ShedLock table.
CREATE TABLE shedlock( name VARCHAR(64) NOT NULL, lock_until TIMESTAMP(3) NOT NULL, locked_at TIMESTAMP(3) NOT NULL, locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name) );
Distributed Locking | Ensures that only one instance of a task runs at a time across multiple nodes. |
Multiple Lock Providers | Supports various lock providers like JDBC, MongoDB, Redis, ZooKeeper, etc. |
Annotations | Uses annotations like @SchedulerLock to easily lock scheduled tasks. |
Configuration | Can be configured using Spring's configuration classes and properties. |
Integration | Seamlessly integrates with Spring's @Scheduled tasks. |
Prevents Duplicate Execution | Ensures that tasks are not executed concurrently in a distributed setup. |
Easy to Use | Simple annotations and configuration make it easy to integrate into existing Spring applications. |
Flexible | Supports various backends for lock storage, making it adaptable to different environments. |