ShedLock Sping-Boot

Navin Kumar
3 min readSep 13, 2021

Many application has that one scheduled task that required to run only one time even after the application is deployed onto multiple pods for load balancing. like: report generation, cleanup job and many more.

Application might be running on single instance there is no issue on the scheduled job which will run only once. but what about the load balancing, if you want your application execution and response must be fast than you need to do load balance for this you need to deployed your application into many pods so it can process user request fast.

In case of reporting, cleanup task you have written scheduled job that need to be executed only once. but due to application running on multiple pods for load balancing it might create multiple execution of these schedulers.

Spring boot Provides @scheduled annotation for scheduler jobs but did not provided the mechanism that will help these Scheduler job to get executed only once if application deployed into multiple instances.

Resolve this issue ShedLock come in picture.

ShedLock is distributed lock for scheduled task. it make sure to execute a task only once at the same time. Once the first Instance acquires lock for scheduled task all the other instance will skip the task execution.

by populating the below values you can handle it very effectively…

  1. name: Name of the scheduled task.
  2. lock_until: How much time will take the current execution.
  3. locked_at: At what time the lock acquired.
  4. locked_by: User who acquired the lock
  5. lockAtMostfor: Maximum time required for the completed execution, it also acts as a safety-net to avoid deadlocks when a node dies and hence is unable to release the lock.
  6. lockAtLeastFor: Minimum time required for the complete execution

How ShedLock actually work.

Just suppose A, B, C & D are 4 different deployment present for an application. Instance A come up and start acquiring the lock on the Scheduled task by checking lock_until must be less than equal to current TimeStamp i.e. [ lock_until ≤ now() ] if it is true then A will update the columns by lock_until = [ now() + lockAtMostFor ], locked_at = [ now() ], locked_by = [ user ], and start the execution.

on the other hand Instance B tried to acquired the schedule task, so it also check for Lock_until ≤ now() but it get false, because instance A already updated the lock_until to greater than now() so instance B get to know that the task is already running by some other instance. similarly all other instance come and try to acquired the lock but get failed and finally the Scheduled task is running on only one instance. once the execution completed and unlocking done the ShedLock update the Lock_until to current timestamp i.e. lock_until = now() this is called slow execution (because the time taken in execution is ≥lockAtMostFor, but what if the execution finishes very fast, in this case we need to set one more variable called lockAtLeastFor.

  1. Very Fast ( lockAtLeastFor = 15s ) : locked acquired at 11:30:00.000, and if the job finished at 11:30:00.450 when unlocking this job, ShedLock sets lock_until to 11:30:15.000.
  2. Slow Execution (lockAtMostFor = 75s) : locked acquired at 11:30:00.000, and if the jov finished at 11:31:16.400 when unlocking this job, ShedLock sets lock_until to now().

--

--