Why Native Java Locks Fail in Distributed Systems and How Redis & Zookeeper Solve It

This article explains the inventory oversell problem caused by Java's JVM‑local locks in multi‑machine deployments, introduces distributed locks as a solution, and compares practical implementations using Redis (including RedLock and Redisson) and Zookeeper (with Curator), providing code snippets, deployment considerations, and a pros‑cons analysis to guide technology selection.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why Native Java Locks Fail in Distributed Systems and How Redis & Zookeeper Solve It

Why Use Distributed Locks?

In a single‑machine e‑commerce system, a user checks inventory stored in Redis before placing an order. When two requests arrive simultaneously and the inventory is 1, both may read the same value and decrement it, resulting in overselling . Using Java's synchronized or ReentrantLock works only within one JVM; in a multi‑machine deployment each JVM has its own lock, so the problem reappears.

Therefore a global, unique lock is required—this is the purpose of a distributed lock, which can be backed by Redis, Zookeeper, or a database.

Redis‑Based Distributed Lock

The simplest approach uses Redis SET key value NX PX ttl to acquire a lock and a Lua script to release it atomically:

// Acquire lock
SET anyLock 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

Use SET NX PX atomically to avoid deadlocks caused by separate set‑and‑expire commands.

Value must be unique so that only the client that set the lock can release it.

Redis can be deployed in three modes: single‑node, master‑slave with Sentinel, or cluster. Single‑node has a single‑point‑of‑failure; master‑slave may lose the lock during failover. The RedLock algorithm mitigates these issues by acquiring the lock on a majority of cluster nodes.

RedLock Algorithm (Redis Cluster)

Get the current timestamp (ms).

Try to create the lock on each master node with a short TTL.

Success requires acquiring the lock on at least N/2+1 nodes.

If the total time to acquire is less than the TTL, the lock is considered valid.

Otherwise, delete any partial locks and retry.

RedLock is still debated and may not guarantee safety in all edge cases.

Redisson Library

Redisson provides a high‑level API that hides the low‑level details and adds a watchdog that automatically extends the lock TTL while the client holds it:

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

The library executes all lock operations via Lua scripts, ensuring atomicity, and the watchdog refreshes the TTL every 10 seconds to avoid accidental expiration.

Zookeeper‑Based Distributed Lock

Zookeeper offers ordered and temporary znodes. The lock algorithm creates a temporary sequential node under a lock path, then:

If the created node has the smallest sequence number, the client holds the lock.

Otherwise, it watches the immediate predecessor node; when that node is deleted, the client re‑checks if it is now the smallest.

This approach leverages Zookeeper's strong consistency and event notifications, avoiding busy‑waiting.

Curator Client

Curator simplifies Zookeeper usage. A typical lock looks like:

InterProcessMutex lock = new InterProcessMutex(client, "/anyLock");
lock.acquire();
// critical section
lock.release();

Internally Curator follows the same ordered‑node algorithm.

Comparison of Redis vs. Zookeeper Locks

Redis advantages :

Very high performance, suitable for high‑throughput scenarios.

Widely available in many infrastructures.

Redis disadvantages :

Lock acquisition may require aggressive retries, consuming CPU.

Data is not strongly consistent; edge cases can cause lock loss.

RedLock does not guarantee 100 % safety.

Zookeeper advantages :

Designed for distributed coordination with strong consistency.

Clients wait on events instead of polling, reducing load.

Zookeeper disadvantages :

High read/write load from many lock/unlock operations can stress the ensemble.

In practice, choose Redis when a high‑performance lock is needed and a Redis cluster already exists; choose Zookeeper when strong consistency and coordination are paramount and a Zookeeper ensemble is available.

Recommendation

If both options are feasible, the author prefers Zookeeper because it avoids the hidden risks of Redis‑based locks. However, the final decision should consider existing infrastructure, performance requirements, and operational constraints.

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.

redisZooKeeperdistributed-lockredisson
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

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.