Skip to content

Distributed Lock Annotation #34652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
dominikcebula opened this issue Mar 25, 2025 · 2 comments
Open

Distributed Lock Annotation #34652

dominikcebula opened this issue Mar 25, 2025 · 2 comments
Labels
status: waiting-for-triage An issue we've not yet triaged or decided on

Comments

@dominikcebula
Copy link

Overview

Introduce @DistributedLock annotation that can be used together with @Scheduled annotation to execute scheduled task only once in a given time window across all instances of the same Microservice.

Problem

Currently when using @Scheduled annotation for Microservices that have more than one instance, Scheduled Task will be executed multiple times across different Microservices instances at the same time.

In some cases you want to execute Scheduled Task only once across all instances of the same Microservice.

Current Solutions

Solutions exists, however they are not as easy as using single @DistributedLock annotation. Some examples include:

  • Introduce custom annotation that will use RDBMS as a synchronization point to hold locks across multiple Microservices
  • Use a Cloud Pattern - for example Create an HTTP function that is triggered by Cloud Scheduler
  • Use Lambda
  • Use Event Queue with Single Consumer
  • Spring Integration Distributed Lock
  • ...

Proposed Solution

Introduce easy to use annotation @DistributedLock that would use some form of abstraction for distributed locks. By default it could use RDBMS.

Usage would look like below:

@DistributedLock(
    lockId = "${payment.check.lock.id}",
    timeout = "${payment.check.lock.timeout}",
    minLockTime = "${payment.check.lock.minLockTime}"
)
@Scheduled(
    fixedDelayString = "${payment.check.task.frequency}",
    initialDelayString = "${payment.check.task.initalDelay}"
)
public void executePaymentCheckTask() {
    ...
}

Details

Min Lock Time

It is important to implement min lock time functionality to prevent execution of the scheduled task multiple times under cases when one instance starts with a slight delay.

Example:

  • task should be executed every 10 seconds
  • task execution time is 2 seconds
  • Instance 2 starts with a 7 seconds delay compared to Instance 1
  • Because of the delay in startup, task schedule looks like below:
    • Instance 1: 09:00:00, 09:00:10, 09:00:20, 09:00:30, ...
    • Instance 2: 09:00:07, 09:00:17, 09:00:27, 09:00:37, ...

Problem: Without min lock time set to 10 seconds, when Instance 1 starts the task at 09:00:00, and when task is finished after 2 seconds at 09:00:02, the Instance 2 would execute the task at 09:00:07.

Solution: Introduce min lock time to prevent the other instance with delayed startup time to execute scheduled task more often then specified by a schedule.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 25, 2025
@mdeinum
Copy link
Contributor

mdeinum commented Mar 25, 2025

The ShedLock library already provides such a feature with many implementations. If you need more control for distributed jobs/scheduling look at libraries like JobRunr or good ol' Quartz.

@dominikcebula
Copy link
Author

Would it be possible to consider having ShedLock as an official Spring Project so that it would be covered by Spring Enterprise Support for LTS as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged or decided on
Projects
None yet
Development

No branches or pull requests

3 participants