spring-projects / spring-projects/spring-framework

Distributed Lock Annotation

Open
#34,652 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

in: core status: waiting-for-triage
Dominant language
Java
Stars
60.2k
Forks
38.8k
Avg merge
5d 2h
Merged PRs (30d)
27

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No files, tests, or implementation entry points are identified. Start by reviewing the existing @Scheduled annotation and scheduling support, then define the distributed-lock abstraction, @DistributedLock integration, and min-lock-time behavior; done requires agreed semantics and tests covering multiple instances and delayed startup.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
backend, distributed-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.