Skip to content
Garvit Joshi edited this page Oct 9, 2026 · 1 revision

@DistributedLock runs a Spring bean method while it holds a lock in Redis. One holder at a time gets the lock of a key, across all instances of the application. With the READ and WRITE types, many readers or one writer get it. The key names what is locked, for example one order. The lease is the time after which Redis drops a lock that was neither released nor renewed.

@DistributedLock(
    key = "order:#{#orderId}",
    type = LockType.REENTRANT,
    waitTime = "5s",
    leaseTime = "",
    onFailure = OnFailure.THROW)
public void process(String orderId) { ... }
Attribute Default Meaning
key required key template; see Key templates
type REENTRANT REENTRANT, READ or WRITE
waitTime "" how long to wait for the lock; blank or zero means try once and give up
leaseTime "" blank: the lock is renewed while held; a value: a fixed lease, not renewed
onFailure THROW THROW, SKIP or HANDLER; see Failure handling
handler not set the LockFailureHandler bean type, required with HANDLER only

Durations are written as 5s, 500ms, 2m or in ISO-8601 form such as PT5S. waitTime must not be negative. leaseTime, when set, must be at least one millisecond.

Lock types

REENTRANT is an exclusive lock that the holding thread may take again, for example when an annotated method calls an annotated method of another bean with the same key. READ is shared: any number of readers hold it while no writer does, and a waiting writer does not hold new readers back (see Limitations). WRITE excludes readers and other writers.

A REENTRANT lock lives at the Redis key locksmith:lock:<key>. READ and WRITE locks live at locksmith:rwlock:<key>; a READ and a WRITE lock with the same key share that one Redis key, which is what makes them exclude each other. A REENTRANT lock and a READ/WRITE lock on the same key are separate locks and do not exclude each other. Pick one kind per key.

When two annotations use exactly the same key text, one with REENTRANT and one with READ or WRITE, startup fails with a LocksmithConfigurationException that names both methods. Keys built from arguments that happen to resolve to the same value are not checked; they simply do not coordinate across the two kinds.

Lease time

Blank leaseTime: renewal. The lock has no fixed end. Redisson renews it in the background for as long as the method runs, and releases it when the method ends. If the JVM dies, renewal stops and the key expires after Redisson's watchdog timeout (30 seconds by default, lockWatchdogTimeout in the Redisson configuration). This is the right choice for almost every method.

Explicit leaseTime: a fixed lease. The lock expires that long after it was acquired, whether the method has finished or not, and it is never renewed. If the method outruns the lease, another instance may take the lock while the method is still running. Locksmith cannot stop that. It detects it at release and logs one WARN, for example:

Lock [locksmith:lock:order:42] was no longer held at release after 2004ms (fixed lease 1000ms);
another instance may have run concurrently: ...

The method's result is returned as usual; the WARN is the only signal.

Related limitations

Clone this wiki locally