10 Hidden Pitfalls of Using Redis Distributed Locks (and How to Avoid Them)
This article examines ten common traps when implementing Redis distributed locks—ranging from non‑atomic setnx/expire operations and missing expirations to lock release ordering, re‑entrancy, master‑slave replication issues, and the Redlock algorithm—providing concrete code examples, explanations, and best‑practice solutions.
Introduction
In high‑concurrency scenarios such as flash‑sale systems, developers often rely on Redis distributed locks to prevent overselling, but many subtle pitfalls can compromise safety and correctness. The following sections detail ten typical problems, illustrate them with Java/Jedis code, and suggest reliable fixes.
1. Non‑atomic setnx + expire
Using SETNX to acquire a lock and then EXPIRE to set its TTL is not atomic. If the process crashes after SETNX but before EXPIRE, the lock becomes permanent and blocks other threads.
if (jedis.setnx(lock_key, lock_value) == 1) {
jedis.expire(lock_key, timeout);
doBusiness // business logic
}2. Overwrite by another client (setnx with expiration time as value)
A workaround stores the expiration timestamp as the value of SETNX. When acquiring the lock, the client compares the stored timestamp with the current time to decide whether the lock has expired.
long expireTime = System.currentTimeMillis() + timeout;
String expireTimeStr = String.valueOf(expireTime);
if (jedis.setnx(lock_key, expireTimeStr) == 1) {
return true;
}
String oldExpireTimeStr = jedis.get(lock_key);
if (oldExpireTimeStr != null && Long.parseLong(oldExpireTimeStr) < System.currentTimeMillis()) {
String oldValueStr = jedis.getSet(lock_key, expireTimeStr);
if (oldValueStr != null && oldValueStr.equals(oldExpireTimeStr)) {
return true;
}
}
return false;This approach still suffers when multiple clients race to call GETSET; the lock’s expiration may be overwritten by another client.
3. Forgetting to set expiration
If a lock is created without an expiration and the process crashes before releasing it, the lock remains forever, causing a deadlock. Always set a TTL when using SETNX or the extended SET command.
4. Forgetting to release the lock after business processing
Even when a TTL is set, relying solely on expiration is inefficient. The lock should be explicitly released as soon as the protected business logic finishes.
if (jedis.set(lockKey, requestId, "NX", "PX", expireTime) == 1) {
doBusiness // business logic
return true;
}
return false;The correct pattern wraps the lock acquisition in a try block and releases the lock in a finally clause.
try {
if (jedis.set(lockKey, requestId, "NX", "PX", expireTime) == 1) {
doBusiness // business logic
return true;
}
return false;
} finally {
unlock(lockKey);
}5. Lock released by another thread (A releases B’s lock)
In a scenario where thread A acquires a lock with a 3‑second TTL, the lock expires before A finishes its long‑running task. Thread B then acquires the same lock. When A finally releases the lock, it unintentionally removes B’s lock.
The fix is to store a unique requestId with the lock and, upon release, verify that the stored value matches the requester’s ID.
try {
if (jedis.set(lockKey, requestId, "NX", "PX", expireTime) == 1) {
doBusiness // business logic
return true;
}
return false;
} finally {
if (requestId.equals(jedis.get(lockKey))) {
unlock(lockKey);
}
}6. Non‑atomic unlock
Checking the lock owner and deleting the key are two separate operations, which can race with another client that has already acquired the lock after expiration. Use a Lua script to perform the check‑and‑delete atomically.
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end7. Lock expires before business completes
If the TTL expires while the protected operation is still running, other threads may acquire the lock prematurely, leading to inconsistent state. One solution is to run a watchdog thread that periodically extends the TTL while the lock holder is still active. The Redisson client implements this “watch‑dog” mechanism automatically.
8. Interaction with @Transactional
When a Spring @Transactional method acquires a Redis lock, the lock may be released before the transaction commits because Spring opens the transaction before the method execution and commits after it returns. This can cause other threads to acquire the lock while the original transaction is still pending.
The correct approach is to acquire the Redis lock **before** the transaction starts, ensuring the lock remains held for the entire transaction duration.
9. Re‑entrancy
Standard Redis locks are non‑re‑entrant: a thread that already holds the lock will block if it tries to acquire it again. Some use‑cases require re‑entrancy, which can be achieved by tracking the owning thread ID and a lock‑count, similar to Java’s ReentrantLock. Redisson provides a built‑in re‑entrant lock implementation.
10. Master‑slave replication pitfalls
In a Redis cluster, a client may acquire a lock on a master node, but the lock key might not yet be replicated to slaves. If the master fails before replication, a slave is promoted, and another client can acquire the same lock, breaking mutual exclusion.
Antirez’s Redlock algorithm mitigates this risk by requiring a majority of independent Redis masters (e.g., 3 out of 5) to grant the lock within a bounded time.
Redlock algorithm steps
Record the current time in milliseconds.
Attempt to acquire the lock on each master sequentially, using a client‑side timeout shorter than the lock’s TTL.
Consider the lock successful only if a majority (N/2+1) of masters grant the lock and the total acquisition time is less than the TTL.
If acquisition fails, release the lock on all masters (even those that did not grant it) to avoid stray locks.
References
Redis distributed lock failure scenarios – https://blog.csdn.net/he247052163/article/details/119413877
Redis re‑entrant lock implementation – https://www.cnblogs.com/x-kq/p/14801527.html
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.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
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.
