Mastering Redis Distributed Locks with Jedis: A Step‑by‑Step Guide
This article introduces Redis’s evolution, key features for distributed locking, explains lock and unlock workflows with Jedis, presents Java code examples, discusses pitfalls like non‑atomic operations, and offers configuration and performance tuning tips for reliable, high‑availability lock services.
Redis Overview
Redis is a high‑performance in‑memory data store that has evolved from version 3.0 to 7.0, adding cluster mode, lazyfree, streams, TLS/ACL, functions, and multi‑part AOF, among other enterprise‑grade features.
Key Features for Distributed Locking
Data structures: String, Hash, List, ZSet can be combined to store lock information.
TTL mechanism: automatic key expiration to release locks after a timeout.
Cluster + master‑slave: provides high availability for lock services.
Ordering: although Redis does not expose a revision number, Lua scripts can enforce atomic operations and preserve request order.
Lock and Unlock Workflow with Jedis
The basic steps are:
Prepare client, key and value.
Attempt to set the key with NX and EX options; if successful, the lock is acquired and the key’s expiration is extended.
If the key already exists, retry according to a back‑off strategy.
On unlock, delete the key only if the stored lock value matches.
Two important evolution points are highlighted:
Non‑atomic SETNX + EXPIRE can leave a permanent lock if the expiration step fails.
Using the extended SET command with NX and EX makes the operation atomic:
SET key value [EX seconds] [PX milliseconds] [NX|XX]Example Java code using Jedis (non‑atomic version):
if (jedis.set(key, lockValue, "NX", "EX", 100) == 1) {
try {
// business logic
} finally {
jedis.del(key); // may delete another client’s lock
}
}To avoid accidental deletion, a random lockValue is generated and compared before deletion:
if (randomLockValue.equals(jedis.get(key))) {
jedis.del(key);
}Because the check and delete are not atomic, a Lua script is introduced to guarantee atomicity:
String script =
"if redis.call('get',KEYS[1]) == ARGV[1] then " +
"return redis.call('del',KEYS[1]) " +
"else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(key),
Collections.singletonList(randomLockValue));
if ("1".equals(result.toString())) {
return true;
}If the business logic exceeds the key’s TTL, the lock may disappear. A watchdog thread periodically extends the TTL to keep the lock alive:
if (jedis.set(key, randomLockValue, "NX", "EX", 100) == 1) {
// lock acquired
// start watchdog to call client.expire(key, ttl) periodically
}Jedis Library Usage
Jedis is the official Java client for Redis. Adding it via Maven:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.0</version>
</dependency>Key API examples:
Locking with extended SET using SetParams:
SetParams params = SetParams.setParams().nx().ex(lockState.getLeaseTTL());
String result = client.set(lockState.getLockKey(), lockState.getLockValue(), params);Unlocking with Lua script via jedis.eval:
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = client.eval(script, 1, lockState.getLockKey(), lockState.getLockValue());Connection Pool Tuning
Jedis can use JedisPool. Important pool parameters include:
maxTotal : maximum connections in the pool (default 8).
maxIdle : maximum idle connections (default 8).
minIdle : minimum idle connections (default 0).
blockWhenExhausted and maxWaitMillis : control waiting behavior when the pool is empty.
testOnBorrow / testOnReturn : enable ping checks (usually disabled for high‑throughput).
jmxEnabled : enable JMX monitoring.
Idle‑resource eviction is governed by testWhileIdle , timeBetweenEvictionRunsMillis , minEvictableIdleTimeMillis , and numTestsPerEvictionRun .
Network Settings
In cluster mode, two critical settings are:
max-redirects : maximum number of redirections when a node fails.
timeout : client socket timeout in milliseconds.
Improper values (e.g., timeout=1000 ms and maxRedirects=2) can cause several‑second stalls during node failures, exhausting thread pools.
Conclusion
The article demonstrates how Redis’s TTL, ordering, and cluster capabilities enable a simple distributed lock, provides a complete Java example with Jedis, and discusses remaining gaps such as re‑entrancy, retry policies, and full production‑grade robustness, which will be addressed in future posts.
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.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
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.
