Distributed Lock Implementations with Redis, Etcd, and Zookeeper

This article explains the concept, application scenarios, and detailed implementations of distributed locks using Redis, Etcd, and Zookeeper, providing Java code examples, lock mechanisms, lease handling, watch features, and a comparative summary of their advantages and drawbacks.

360 Tech Engineering
360 Tech Engineering
360 Tech Engineering
Distributed Lock Implementations with Redis, Etcd, and Zookeeper

What is a distributed lock? A distributed lock controls access to a shared resource when multiple processes run across different machines in a distributed system.

Application scenarios include high‑concurrency and high‑traffic environments where single‑machine lock mechanisms fail.

Redis‑based distributed lock

Implementation steps:

Lock acquisition using a Lua script on a selected Redis node.

Mutual exclusion is ensured by retrying the script until the lock is obtained.

Supports re‑entrancy, watchdog auto‑extension, and explicit release.

Example code:

private RedissonClient getClient(){
    Config config = new Config();
    config.useSingleServer().setAddress("redis://127.0.0.1:6379");
    RedissonClient redissonClient = Redisson.create(config);
    return redissonClient;
}

@Test
public void test() throws Exception {
    int[] count = {0};
    for (int i = 0; i < 10; i++) {
        RedissonClient client = getClient();
        final RedisLock redisLock = new RedisLock(client, "lock_key");
        executorService.submit(() -> {
            try {
                redisLock.lock();
                count[0]++;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try { redisLock.unlock(); } catch (Exception e) { e.printStackTrace(); }
            }
        });
    }
    executorService.shutdown();
    executorService.awaitTermination(1, TimeUnit.HOURS);
    System.out.println(count[0]);
}

RedLock (multi‑node) example:

public static RLock create(String url, String key) {
    Config config = new Config();
    config.useSingleServer().setAddress(url);
    RedissonClient redissonClient = Redisson.create(config);
    return redissonClient.getLock(key);
}

RedissonRedLock redissonRedLock = new RedissonRedLock(
    create("redis://127.0.0.1:6379", "lock_key1"),
    create("redis://127.0.0.1:6380", "lock_key2"),
    create("redis://127.0.0.1:6381", "lock_key3")
);
RedisRedLock redLock = new RedisRedLock(redissonRedLock);
// test code omitted for brevity

Etcd‑based distributed lock analysis

Key mechanisms:

Lease (TTL) ensures automatic lock release when the holder crashes.

Revision provides a total order for write operations, enabling fair lock acquisition.

Prefix creates unique lock keys under a common path.

Watch monitors predecessor keys to avoid the “herd effect”.

Implementation steps:

Establish a client connection and create a unique key with a lease.

Start a periodic task to keep the lease alive.

Write the key to Etcd and record its revision.

Determine lock ownership by comparing revisions; if not the smallest, watch the predecessor key.

Execute business logic once the lock is acquired.

Delete the key to release the lock.

Example code:

public class EtcdDistributeLock extends AbstractLock {
    private Client client;
    private Lock lockClient;
    private Lease leaseClient;
    private String lockKey;
    private String lockPath;
    private AtomicInteger lockCount;
    private Long leaseTTL;
    private Long initialDelay = 0L;
    private ScheduledExecutorService service = null;
    private final ConcurrentMap<Thread, LockData> threadData = Maps.newConcurrentMap();
    // constructors, lock(), unlock(), keep‑alive runnable omitted for brevity
}

Zookeeper‑based distributed lock

Implementation principle:

Clients create temporary sequential nodes under a lock path.

The node with the smallest sequence number holds the lock.

If not the smallest, a client watches the predecessor node and retries when it disappears.

Example code:

public class ZKLock extends AbstractLock {
    private CuratorFramework client;
    private InterProcessLock lock;
    public ZKLock(String zkAddress, String lockPath) {
        client = CuratorFrameworkFactory.newClient(zkAddress, new RetryNTimes(5, 5000));
        client.start();
        this.lock = new InterProcessMutex(client, lockPath);
    }
    @Override
    public void lock() {
        try { lock.acquire(); } catch (Exception e) { throw new RuntimeException(e); }
    }
    @Override
    public void unlock() {
        try { lock.release(); } catch (Exception e) { throw new RuntimeException(e); }
    }
    // tryLock overloads omitted
}

Summary

1. Redis locks (single‑instance Redisson) are simple but vulnerable to node failure; RedLock improves reliability with multiple instances at higher cost.

2. Zookeeper locks offer high availability and re‑entrancy but have lower performance due to frequent node creation/deletion.

3. Etcd locks combine the strengths of Zookeeper with stronger consistency guarantees, leveraging leases, revisions, prefixes, and watches to provide a fair, reliable distributed lock suitable for high‑load scenarios.

Distributed Lock
360 Tech Engineering
Written by

360 Tech Engineering

Official tech channel of 360, building the most professional technology aggregation platform for the brand.

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.