Mastering Distributed Locks with Redis: From Simple SETNX to RedLock and Redisson
This article explains how to implement distributed locks using Redis, covering basic SETNX/EXPIRE techniques, common pitfalls, atomic Lua scripts, the RedLock algorithm, and practical Redisson usage, while providing Java code examples and best‑practice recommendations.
1. Overview
In multithreaded environments Java uses
synchronizedor
ReentrantLockfor local locks, but distributed systems need a mechanism to synchronize threads across nodes.
Distributed lock characteristics
Mutual exclusion: only one thread can hold the lock at a time.
Reentrancy: the same thread can acquire the lock multiple times on the same node.
Lock timeout: similar to J.U.C. locks, supports expiration to avoid deadlocks.
High performance and availability: lock/unlock must be efficient and highly available.
Blocking and non‑blocking: the lock can be released promptly from a blocked state.
2. Rough Redis implementation
Redis is a shared storage system suitable for distributed locks because of its high read/write performance.
The
SETcommand with the
NXoption implements "set if not exists" semantics:
If the key does not exist, the command succeeds and the lock is acquired.
If the key exists, the command fails and the lock is not acquired.
To release the lock, delete the key.
Set an appropriate expiration time to avoid deadlocks.
<code>// Try to acquire lock
if (setnx(key, 1) == 1) {
// Set expiration time
expire(key, 30);
try {
// TODO business logic
} finally {
// Release lock
del(key);
}
}</code>The above implementation has several problems:
Non‑atomic operations: multiple commands are not atomic, leading to possible deadlocks.
Lock mis‑release: if a thread blocks and the lock expires, another thread may acquire it, and the original thread may later delete the lock belonging to the other thread.
Business timeout auto‑unlock: the lock may be released while business logic is still running.
Non‑reentrant lock: the implementation does not support reentrancy.
3. Solving remaining issues
3.1 Mis‑delete scenario
When a thread holding the lock blocks and its TTL expires, the lock is automatically released; another thread can acquire it, and later the original thread may mistakenly delete the new lock.
3.2 Solution
Store the thread identifier when acquiring the lock.
When releasing, verify that the stored identifier matches the current thread.
<code>// Try to acquire lock
if (setnx(key, "currentThreadId") == 1) {
expire(key, 30);
try {
// TODO business logic
} finally {
if ("currentThreadId".equals(get(key))) {
del(key);
}
}
}</code>This ensures only the owner can release the lock and enables reentrancy by incrementing a counter for the same thread.
3.3 Atomicity guarantee
SETNX and EXPIRE are not atomic; if the server crashes after SETNX succeeds but before EXPIRE, the lock may never expire. Use a Lua script to combine the operations atomically:
<code>-- Set expiration atomically
if (redis.call('setnx', KEYS[1], ARGV[1]) < 1) then
return 0;
end;
redis.call('expire', KEYS[1], tonumber(ARGV[2]));
return 1;
-- Delete lock atomically
if (redis.call('get', KEYS[1]) == ARGV[1]) then
return redis.call('del', KEYS[1]);
end;
return 0;</code>Calling this script from Java provides an atomic lock acquisition and release.
3.4 Automatic timeout unlock
If a thread's execution exceeds the TTL, the lock will still expire. One approach is to set a long TTL, but a better solution is to start a watchdog thread that renews the TTL before it expires.
4. Pros and cons of Redis‑based locks
Advantages
High performance.
Easy to implement using
SETNX.
Avoids single‑point failure because Redis can be clustered.
Disadvantages
Choosing an appropriate timeout is difficult.
In master‑slave replication the data is asynchronous; a master failure before replication can cause lock loss.
5. Cluster issues
5.1 Master‑slave cluster
If a lock is set on the master but not yet replicated to the slave, and the master crashes, the lock is lost.
5.2 Split‑brain
Network partitions can cause multiple masters, leading to duplicate locks.
6. RedLock
RedLock is an algorithm that acquires locks on multiple independent Redis nodes. If a client obtains locks on a majority of nodes (N/2+1) within the lock’s TTL, the lock is considered acquired.
Get current Unix time in milliseconds.
Try to acquire the lock on each Redis instance with the same key and a unique value (e.g., UUID), using a short network timeout.
Measure the time spent acquiring the lock.
If a majority of nodes grant the lock and the elapsed time is less than the lock’s TTL, the lock is successful.
If acquisition fails, release the lock on all nodes.
In short, success requires a majority of nodes to grant the lock and the total acquisition time to be less than the lock’s expiration.
7. Redisson
7.1 Simple implementation
Redisson is a Java client for Redis that provides distributed locks, collections, and objects.
<code>// Acquire distributed lock
RLock lock = redissonClient.getLock("myLock");
try {
// Wait up to 10 seconds, lock expires after 30 seconds
boolean locked = lock.tryLock(10, 30, TimeUnit.SECONDS);
if (locked) {
System.out.println("Lock acquired, executing business logic...");
} else {
System.out.println("Failed to acquire lock...");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
redissonClient.shutdown();
}</code>Redisson stores lock information in a hash where the field is the thread identifier and the value is the reentrancy count.
7.2 Watchdog mechanism
When a lock is set, Redisson starts a watchdog thread that periodically renews the lock’s TTL (default 30 seconds). This ensures the lock remains valid even if the client experiences temporary network issues or long‑running business logic.
The watchdog checks whether the client still holds the lock and extends the expiration time; if the lock cannot be renewed, it expires and other clients can acquire it.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.