Is Redis Redlock Really Safe? Uncovering the Truth Behind Distributed Locks
This article thoroughly examines the safety of Redis-based distributed locks, from basic SETNX implementations to advanced Redlock algorithms, compares them with Zookeeper locks, discusses common pitfalls like deadlocks, clock drift, and network delays, and presents expert debates and practical solutions for robust lock management.
Why Do We Need Distributed Locks?
In a micro‑service architecture multiple processes may need to modify the same resource (e.g., a MySQL row). A distributed lock provides mutual exclusion across processes, unlike a single‑process lock.
How to Implement a Distributed Lock with Redis
The simplest approach uses SETNX to create a key only if it does not exist, then DEL to release it.
<code>127.0.0.1:6379> SETNX lock 1
(integer) 1 // lock acquired
127.0.0.1:6379> SETNX lock 1
(integer) 0 // lock acquisition failed</code>This basic scheme suffers from deadlocks when a client crashes or fails to release the lock.
How to Avoid Deadlocks
Assign an expiration time to the lock so it is automatically released after a timeout.
<code>127.0.0.1:6379> SETNX lock 1 // acquire
(integer) 1
127.0.0.1:6379> EXPIRE lock 10 // 10 s TTL
(integer) 1</code>However, SETNX and EXPIRE are two separate commands, so a failure between them can still leave a stale lock.
Atomic Lock Acquisition (Redis 2.6.12+)
<code>127.0.0.1:6379> SET lock 1 EX 10 NX
OK</code>This single command guarantees atomic creation with a TTL.
Preventing “Lock Released by Someone Else”
Store a unique identifier (e.g., a UUID) as the lock value and verify it before deletion.
<code># Acquire with UUID
127.0.0.1:6379> SET lock $uuid EX 20 NX
OK
# Release safely (Lua script)
if redis.call("GET",KEYS[1]) == ARGV[1] then
return redis.call("DEL",KEYS[1])
else
return 0
end</code>The Lua script ensures the check‑and‑delete operation is atomic.
Redlock – The Multi‑Instance Algorithm
Redlock attempts to solve lock loss during master‑slave failover by acquiring the lock on at least three out of five independent Redis masters.
Record start timestamp T1.
Send SET key value EX ttl NX to each instance; stop after a failure.
If ≥3 instances succeed, record timestamp T2 and verify T2‑T1 < ttl . If true, the lock is considered acquired.
Perform the protected operation.
If acquisition fails, release any partial locks on all nodes.
Key safety points: majority success, total acquisition time must be less than the TTL, and releasing locks on all nodes.
Debate: Martin vs. Antirez
Martin (Cambridge) argues that Redlock relies on synchronized clocks and cannot guarantee correctness under network delay, process pause, or clock drift. He proposes a fencing‑token approach that uses a monotonically increasing token to enforce ordering.
Antirez (Redis author) counters that precise clock sync is unnecessary; a bounded clock error is acceptable, and the algorithm already detects excessive acquisition time in step 3. He also notes that any lock service suffers from post‑acquisition failures (e.g., GC pauses), not just Redlock.
Zookeeper Locks
Zookeeper creates an ephemeral node; as long as the client’s session remains alive (heartbeat), the lock persists. If the client crashes, the session expires and the node is removed.
However, long GC pauses or network loss can cause the session to expire, leading to the same “lock held by a dead client” problem.
Practical Takeaways
Use simple Redis SET EX NX with a unique value and a Lua release script for most cases.
Consider Redlock only when you can guarantee reasonably synchronized clocks and need high availability across multiple Redis instances.
For strict correctness, combine a distributed lock with a fencing‑token or application‑level version check.
Zookeeper offers automatic lock release via ephemeral nodes but suffers from session‑heartbeat dependencies.
Conclusion
Distributed locks improve concurrency safety but are not 100 % reliable under extreme conditions. Choose the implementation that matches your consistency requirements, operational constraints, and tolerance for complexity.
Sanyou's Java Diary
Passionate about technology, though not great at solving problems; eager to share, never tire of 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.