Avoid Common Redis Distributed‑Lock Pitfalls and Fix Them
This article explains why naive Redis lock usage can cause non‑atomic operations, forgotten releases, lock‑stealing, re‑entrancy, read‑write contention, segmentation, timeout, master‑slave failures, and offers practical Java/Redisson/Lua solutions to make distributed locks reliable.
Redis distributed locks are popular for their simplicity and efficiency, but improper use can lead to serious problems.
Non‑Atomic Lock Acquisition
Using SETNX followed by EXPIRE is not atomic; if setting the timeout fails, the lock may never expire and consume memory.
if (jedis.setnx(lockKey, val) == 1) {
jedis.expire(lockKey, timeout);
}Forgotten Release
Even if the lock is set atomically with SET (NX, PX), forgetting to release it or releasing it at the wrong time can cause other threads to acquire a stale lock.
String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
if ("OK".equals(result)) {
return true;
}
return false;Releasing Someone Else's Lock
When a lock expires and another thread acquires it, the original thread may still try to release the lock, deleting a lock it does not own. Use a unique requestId to verify ownership before deletion.
if (jedis.get(lockKey).equals(requestId)) {
jedis.del(lockKey);
return true;
}
return false;Lua Scripts for Atomic Release
Lua ensures the check‑and‑delete operation is atomic.
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
endRe‑entrant Locks
Standard Redis locks are not re‑entrant. Redisson provides a re‑entrant lock that tracks a counter per requestId.
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
redis.call('hincrby', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil;
endRead‑Write Locks
Redisson implements read‑write locks where multiple readers share the lock while writers obtain exclusive access.
RReadWriteLock rwLock = redisson.getReadWriteLock("readWriteLock");
RLock rLock = rwLock.readLock();
try { rLock.lock(); /* business */ } finally { rLock.unlock(); }Lock Segmentation
Splitting a large lock into many smaller segments (e.g., 100 shards) reduces contention in high‑traffic scenarios such as flash sales.
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.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
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.
