Implementing Distributed Locks with Redis and Redisson in Java
The article explains why Java's synchronized lock cannot be used for distributed scenarios, demonstrates how to build a Redis‑based distributed lock with setIfAbsent, discusses pitfalls such as server crashes and lock expiration, and presents robust solutions including atomic expiration, thread‑ID verification, lock renewal, and Redisson usage.
In distributed systems a JVM‑level synchronized lock cannot guarantee mutual exclusion across multiple instances, so a Redis‑based lock is needed.
Using setIfAbsent (SETNX) you can attempt to acquire a lock by storing a key only if it does not already exist; if the call returns false the lock acquisition fails.
Simple acquisition without expiration can lead to deadlocks when a server crashes before releasing the lock. Adding an explicit timeout with expire mitigates this, but the timeout and the lock acquisition must be atomic to avoid a window where the lock is held without an expiration.
Redis provides an atomic operation that sets the value and its TTL in a single call:
Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "product_001_lock", 30, TimeUnit.SECONDS);To prevent a thread that timed out from releasing another thread's lock, store a unique client identifier with the lock and verify it before deletion:
String clientId = UUID.randomUUID().toString();
Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS);
...finally {
if (clientId.equals(stringRedisTemplate.opsForValue().get(lockKey))) {
stringRedisTemplate.delete(lockKey);
}
}For more advanced scenarios, Redisson offers a high‑level API. The lock object is obtained with redisson.getLock(lockKey) and can be locked, used, and safely unlocked, while Redisson handles automatic lock renewal (watch‑dog) behind the scenes.
RLock redissonLock = redisson.getLock(lockKey);
try {
redissonLock.lock();
// critical section
} finally {
redissonLock.unlock();
}In summary, a correct distributed lock implementation must ensure mutual exclusion, avoid deadlocks through expiration, bind lock and unlock to the same logical thread (or client ID), and preferably use atomic operations or libraries like Redisson that encapsulate these concerns.
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.
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.
