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.

Didi Tech
Didi Tech
Didi Tech
Distributed Locks: Concepts, Evolution, and Implementation Strategies

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_key

Scheme 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_key

Scheme 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_key

Scheme 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 end

The 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencyredisSystem DesignZooKeeperdistributed-lockredisson
Didi Tech
Written by

Didi Tech

Official Didi technology account

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.