Databases 17 min read

Implementing Distributed Locks with Databases, Redis, and Zookeeper

This article explains how to build distributed locks using three different technologies—database tables, Redis, and Zookeeper—detailing their implementation steps, code examples, advantages, drawbacks, and practical considerations for choosing the right solution in real‑world scenarios.

58 Tech
58 Tech
58 Tech
Implementing Distributed Locks with Databases, Redis, and Zookeeper

This article introduces three common ways to implement distributed locks: using a relational database table, using Redis, and using Zookeeper. It explains the underlying principles, provides concrete code snippets, discusses the pros and cons of each approach, and offers guidance on when to choose which solution.

1. Database Table Lock

Creating a lock table:

CREATE TABLE `t_ms_lock` (
    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'primary key',
    `name` varchar(64) NOT NULL DEFAULT '' COMMENT 'method name to lock',
    `desc` varchar(1024) NOT NULL DEFAULT 'description',
    `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'record time',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uidx_name` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='locked methods';

Lock acquisition (insert) and release (delete):

insert into t_ms_lock(name,desc) values ('name','desc');
delete from t_ms_lock where name='name';

Because the name column has a unique constraint, only one insert can succeed, granting the lock to that thread. The article lists several problems with this simple approach, such as single‑point database failure, missing expiration, non‑blocking behavior, and lack of re‑entrancy, and suggests possible mitigations (dual databases, cleanup tasks, retry loops, extra columns for re‑entrancy).

2. Database Exclusive Lock (FOR UPDATE)

Using InnoDB row‑level locking:

public boolean lock() {
    connection.setAutoCommit(false);
    while (true) {
        ResultSet rs = connection.executeQuery("SELECT * FROM t_ms_lock WHERE name='xxx' FOR UPDATE");
        if (rs.next() == null) {
            return true; // lock acquired
        }
    }
    return false;
}

Unlocking simply commits the transaction:

public void unlock() {
    connection.commit();
}

The article warns that MySQL may fall back to table‑level locks if it decides a full table scan is cheaper, and that long‑running exclusive locks can exhaust connection pools.

3. Database Optimistic Lock

Adding a version column to the lock table allows a compare‑and‑swap style update: read the version, attempt to update with WHERE version = oldVersion, and increment the version on success. If the version has changed, the update fails, indicating the lock is held elsewhere.

4. Redis Distributed Lock

Simple implementation using SET key value NX PX ttl and a Lua script for safe release:

// Acquire lock
SET d_lock unique_value NX PX 30000
// Release lock (Lua script)
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end

Key points: use the atomic SET … NX PX command, ensure the value is unique, and delete only if the stored value matches. Deployment options (single‑node, master‑slave with Sentinel, cluster) are discussed, as well as the RedLock algorithm for higher reliability.

Redisson, a Java client, abstracts these details. Example configuration and usage:

Config config = new Config();
config.useClusterServers()
    .addNodeAddress("redis://192.168.1.101:7001")
    .addNodeAddress("redis://192.168.1.101:7002")
    .addNodeAddress("redis://192.168.1.101:7003")
    .addNodeAddress("redis://192.168.1.102:7001")
    .addNodeAddress("redis://192.168.1.102:7002")
    .addNodeAddress("redis://192.168.1.102:7003");
RedissonClient redisson = Redisson.create(config);
RLock lock = redisson.getLock("d_lock");
lock.lock();
// business logic
lock.unlock();

Redisson’s watchdog automatically extends the lock’s TTL every 10 seconds, preventing accidental expiration while the lock is held.

5. Zookeeper Distributed Lock

Zookeeper provides ordered, temporary znodes and watch events. The typical algorithm creates an EPHEMERAL‑SEQUENTIAL node under /lock, checks if it has the smallest sequence number, and if not, sets a watch on the predecessor node.

When the predecessor node is deleted, the watch triggers and the client re‑checks if it now holds the smallest sequence, thus acquiring the lock.

Curator, a high‑level Zookeeper client, simplifies this with InterProcessMutex:

InterProcessMutex ipm = new InterProcessMutex(client, "/d_lock");
ipm.acquire();
// critical section
ipm.release();

The core loop of Curator’s lock implementation is also shown, illustrating how it watches the previous node and retries until the lock is obtained.

6. Comparison of Redis vs Zookeeper

Redis locks are simple and high‑performance but suffer from single‑point failures and weaker consistency; RedLock mitigates some issues but is still debated. Zookeeper offers strong consistency, robust lock semantics, and low‑polling overhead, but can become a bottleneck under heavy lock churn.

7. Summary

The article concludes that no single solution is perfect; the choice depends on application requirements such as complexity, reliability, and performance, similar to the CAP theorem trade‑offs.

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.

databaseconcurrencyZooKeeperdistributed-lock
58 Tech
Written by

58 Tech

Official tech channel of 58, a platform for tech innovation, sharing, and communication.

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.