Distributed Locks: Concepts, Evolution, and Implementation Strategies
Distributed locks provide mutual exclusion across multiple nodes in scalable, reliable systems, and can be implemented via simple Redis SETNX/EX patterns, ZooKeeper’s EPHEMERAL_SEQUENTIAL znodes with watches, or Redisson’s advanced Java‑centric primitives, each offering distinct trade‑offs in simplicity, consistency, and feature richness.
Distributed locks are synchronization primitives used in distributed systems to ensure mutual exclusion of shared resources across multiple nodes. This article introduces the terminology, the problems they solve, and the characteristics of distributed environments.
1. Problem Introduction
When multiple services concurrently modify a shared value (e.g., service A adds 200 to X while service B subtracts 100), race conditions can produce incorrect results. The root cause is the lack of mutual exclusion.
2. Characteristics of Distributed Environments
• Scalability – horizontal scaling improves throughput. • High reliability – the system tolerates node failures. • High concurrency – many machines process requests in parallel. • Cost‑effective – many small machines replace a single powerful one.
3. Locks in Single‑process/Thread Contexts
Traditional locks include mutexes (e.g., sync.Mutex in Go, ReentrantLock in Java) and semaphores for inter‑process coordination.
4. Distributed Locks
Distributed locks must work across different processes, machines, or containers. They require a lock space that is globally accessible, a unique identifier, and at least two states (locked/unlocked).
5. Implementation Schemes
5.1 Naïve Redis Solutions
Several Redis‑based patterns are discussed:
Scheme 1 – SETNX + DEL:
1 setnx lock_key lock_value
2 // do sth
3 del lock_keyScheme 2 – SETNX + SETEX (adds timeout):
1 setnx lock_key lock_value
2 setex lock_key N lock_value // N seconds timeout
3 // do sth
4 del lock_keyScheme 3 – atomic SET with NX and EX (single‑step lock):
1 SET lock_key lock_value EX N NX // N seconds timeout
2 // do sth
3 del lock_keyScheme 4 – Lua script to delete only if the value matches (prevents accidental unlock of another client):
1 if redis.call("get",KEYS[1]) == ARGV[1] then
2 return redis.call("del",KEYS[1])
3 else
4 return 0
5 endThe atomic SET … NX EX pattern (Scheme 3) is the most widely used because of its simplicity and low overhead.
5.2 ZooKeeper Solution
ZooKeeper provides a coordination service with strong consistency. By creating an EPHEMERAL_SEQUENTIAL znode under a lock root, the client that creates the smallest sequential node acquires the lock. Other clients watch the predecessor node to avoid the herd effect.
Typical ZK operations:
create, delete, exists, setData, getChildren.
Java example using Curator:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.11.1</version>
</dependency> public class TestLock {
public static void main(String[] args) throws Exception {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient("ip:port", retryPolicy);
client.start();
InterProcessMutex mutex = new InterProcessMutex(client, "/sunnyzengqi/curator/lock");
mutex.acquire();
System.out.println("Enter mutex");
Thread.sleep(10000);
mutex.release();
client.close();
}
}This approach leverages ZooKeeper’s session expiration and watch mechanisms to provide long‑lasting locks and event‑driven lock acquisition.
5.3 Redisson Solution
Redisson is a Java client for Redis that offers high‑level distributed primitives, including re‑entrant, fair, and read‑write locks. It uses a watchdog thread to automatically extend the lock’s TTL while the client is alive, avoiding deadlocks caused by client crashes.
6. Summary
The three main implementations each have trade‑offs:
Redis (naïve) – simple, language‑agnostic, but limited in advanced features.
ZooKeeper – strong consistency, session‑based lock duration, watch‑driven notifications; best for Java ecosystems.
Redisson – builds on Redis, adds advanced lock types and automatic TTL extension, but is Java‑only.
Choosing a solution depends on the required lock semantics, language stack, and operational environment.
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.
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.
