Evolution of Distributed Locks with Redis and Redisson
This article walks through the step‑by‑step evolution of Redis‑based distributed lock implementations—from simple SETNX locking to atomic expiration, UUID‑based ownership, Lua‑scripted safe release, and finally using Redisson’s high‑level lock API—illustrating common pitfalls and robust solutions.
Distributed locks are a fundamental technique for ensuring that only one process performs a critical section of code; they can be implemented using a shared resource such as Redis where a key is "occupied" (SETNX) and the process either proceeds or waits until the lock is released.
Phase 1 shows a naive implementation that acquires a lock with stringRedisTemplate.opsForValue().setIfAbsent("lock", "111"), executes business logic, and deletes the lock. The problem is that if the business code throws an exception or the process crashes, the lock is never released, causing a deadlock.
The first fix is to set an automatic expiration on the lock so it will be removed even if the delete step is missed:
Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("lock", "111");
if (lock) {
stringRedisTemplate.expire("lock", 30, TimeUnit.SECONDS);
// business logic
stringRedisTemplate.delete("lock");
} else {
Thread.sleep(100);
return getCatalogJsonDbWithRedisLock();
}However, a crash between the SETNX and the EXPIRE call can still leave the lock without an expiration, leading to another deadlock. The solution is to use the atomic SET key value EX seconds NX command, which combines acquisition and expiration.
Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("lock", "111", 30, TimeUnit.SECONDS);
if (lock) {
// business logic
stringRedisTemplate.delete("lock");
} else {
Thread.sleep(100);
return getCatalogJsonDbWithRedisLock();
}To avoid deleting a lock that may have been taken over by another process after expiration, a unique identifier (UUID) is stored as the lock value. Only the owner whose UUID matches the stored value is allowed to delete the lock.
String uuid = UUID.randomUUID().toString();
ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
Boolean lock = ops.setIfAbsent("lock", uuid, 5, TimeUnit.SECONDS);
if (lock) {
// business logic
String lockValue = ops.get("lock");
if (uuid.equals(lockValue)) {
stringRedisTemplate.delete("lock");
}
} else {
Thread.sleep(100);
return getCatalogJsonDbWithRedisLock();
}Even with a UUID, a race condition can occur when the lock expires just before the owner attempts to delete it, potentially removing another process's lock. The safe way is to perform the check‑and‑delete atomically using a Lua script:
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then
" +
" return redis.call(\"del\",KEYS[1])
" +
"else
" +
" return 0
" +
"end";
stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class),
Arrays.asList("lock"), lockValue);The final robust implementation combines UUID ownership, atomic expiration, and Lua‑scripted release, handling long‑running business logic and ensuring that lock acquisition and release are both safe and atomic.
Beyond custom implementations, Redisson provides a high‑level Java library built on Redis that offers distributed objects (Map, Set, List, etc.) and services (Lock, Semaphore, CountDownLatch, Bloom filter, etc.). Using Redisson, developers can acquire a distributed lock with a single API call, letting Redis handle expiration, renewal, and safe release internally.
For more details, refer to the Redisson documentation at https://github.com/redisson/redisson/wiki .
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
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.
