Redis Distributed Locks: SETNX, Lua Scripts, Redisson & Redlock Algorithm

This article explains four approaches to implementing distributed locks with Redis: basic SETNX with expiration, atomic Lua scripts for lock acquire/release, the Redisson Java client with watchdog renewal, and the Redlock algorithm for high-availability multi-master deployments.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Redis Distributed Locks: SETNX, Lua Scripts, Redisson & Redlock Algorithm

In distributed systems, controlling access to shared resources requires distributed locks. Unlike single-process locks using synchronized, distributed deployments need coordination across nodes. A typical scenario: a Spring Quartz scheduled task runs on multiple cluster nodes simultaneously, causing duplicate processing unless a distributed lock ensures only one executes.

1. Using SETNX Command

SETNX key value

sets a key only if it does not exist, returning 1 on success (lock acquired) or 0 on failure. To prevent deadlocks, an expiration must be set via EXPIRE, but these two commands are not atomic: if the process crashes after SETNX but before EXPIRE, the key never expires and other threads cannot acquire the lock.

Since Redis 2.6.12, SETNX is deprecated. The atomic replacement is:

SET key value [NX | XX] [GET] [EX seconds | PX milliseconds]
NX

: set only if key does not exist XX: set only if key exists EX: expire in seconds PX: expire in milliseconds SET ... NX EX is atomic, but using DEL to release the lock risks deleting another client's lock if the original lock expired and a new one was acquired.

2. Using Lua Scripts for Atomicity

Lua scripts execute atomically via EVAL. The lock script checks SETNX and sets expiry in one step:

if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then
  redis.call('expire',KEYS[1],ARGV[2])
  return 1
else
  return 0
end;

Unlock script verifies ownership before deletion:

if redis.call('get',KEYS[1]) == ARGV[1] then
  return redis.call('del',KEYS[1])
else
  return 0
end;

A complete Java example ( RedisDistributeLock) wraps these scripts, taking a RedisClient, lock key, unique client value, and expiry time in milliseconds. The lock() method calls eval with the lock script; unlock() calls eval with the unlock script. Usage:

RedisDistributeLock lock = new RedisDistributeLock(jedis, "mylock", "myclient", 2000);
if (lock.lock()) {
  try { System.out.println("Lock acquired!"); }
  finally { lock.unlock(); }
}

3. Using Redisson Client

Redisson (version 3.35.0) provides high-level distributed locks with automatic lease renewal (watchdog). Maven dependency:

<dependency>
  <groupId>org.redisson</groupId>
  <artifactId>redisson</artifactId>
  <version>3.35.0</version>
</dependency>

Spring configuration creates a RedissonClient bean pointing to redis://127.0.0.1:6379. Acquiring a lock:

RLock lock = redissonClient.getLock("fullstack_lock");
try {
  lock.tryLock(3, 30, TimeUnit.SECONDS);
  System.out.println("Lock acquired!");
} finally {
  lock.unlock();
}

Internally, Redisson executes Lua scripts and runs a background watchdog thread that extends the lock TTL while the holder is alive, preventing premature expiry during long operations.

4. Redlock Algorithm for High Availability

In master-slave replication, if the master fails after a client acquires the lock but before replication completes, the promoted slave lacks the lock key, allowing another client to acquire it — violating mutual exclusion.

Antirez proposed Redlock: deploy N independent Redis masters (no replication). Steps:

Record start time in milliseconds.

Sequentially attempt lock on each instance with same key/value; timeout per instance must be far less than total lock TTL (e.g., 5–50 ms vs 10 s) to avoid blocking on down nodes.

Lock succeeds only if majority (N/2+1) instances acquire it AND total elapsed time < lock TTL.

Effective TTL = initial TTL − elapsed time.

On failure (insufficient majority or timeout), send unlock to all instances.

Redlock's safety was debated by Martin Kleppmann; see Redis official site for details.

5. Summary

Redis offers multiple distributed lock patterns: simple SET NX EX for basic cases, Lua scripts for atomic check-and-set, Redisson for production-ready features (watchdog, fair locks, pub/sub), and Redlock for high-availability requirements. For systems demanding strong consistency (CP), ZooKeeper or etcd may be preferable over Redis (CA).

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.

Distributed SystemsJavaRedisdistributed-lockredissonredlocklua-scriptsetnx
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

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.