Databases 10 min read

Understanding Redis Locks: setnx, RedLock, and Redisson

This article explains the fundamentals of Redis locking mechanisms, including the setnx command, the RedLock algorithm, and how the Redisson Java client implements distributed locks with Lua scripts, highlighting pitfalls, best practices, and code examples for safe lock acquisition and release.

Architecture Digest
Architecture Digest
Architecture Digest
Understanding Redis Locks: setnx, RedLock, and Redisson

When discussing Redis locks, three high‑frequency terms appear most often: setnx , RedLock , and Redisson .

setnx is usually not just the literal SETNX key value command. In modern Redis it refers to using the SET command with the NX option, which only succeeds when the key does not already exist. The full syntax is:

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

The lock works because the key must be absent for the SET to succeed; the process that acquires the lock holds the key, and any other process fails to acquire it while the key exists.

To avoid a dead lock when the holder crashes, an expiration is added, e.g. PX 30000 (30 seconds). Without it, a process could keep the lock indefinitely.

Even with expiration, race conditions can occur: if the holder exceeds the timeout, another process may acquire the lock and later the original holder might delete the key, unintentionally releasing the new lock. To mitigate this, the lock value should contain a unique client identifier (e.g., a UUID) and the unlock logic must verify that the stored value matches the owner before deleting.

Typical pseudo‑code for this pattern is:

String uuid = xxxx;
// set lock with unique value and expiration
set Test uuid NX PX 3000
try {
    // business logic ...
} finally {
    // unlock
    if (uuid.equals(redisTool.get('Test'))) {
        redisTool.del('Test');
    }
}

However, the GET and DEL operations are not atomic, leaving a small window for race conditions.

Using a Lua script guarantees atomicity because the entire script runs as a single Redis command. An example script for safe unlock is:

-- Lua script to delete lock atomically
-- KEYS[1] = lock key, ARGV[1] = expected UUID
if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
else
    return 0
end

Redisson, a Java Redis client, provides high‑level APIs for distributed locks that internally use such Lua scripts. Its RedissonLock class implements lock acquisition and release via Lua, offering a ready‑to‑use solution.

Redisson also supports the RedLock algorithm, a distributed lock design proposed by Redis authors. RedLock requires a majority of independent Redis instances (N/2 + 1) to acquire the lock within a short timeout. The algorithm proceeds as follows:

Attempt to lock each of the N nodes sequentially.

Skip nodes that exceed the configured timeout.

If at least (N/2 + 1) nodes grant the lock and the total time is less than the lock’s TTL, consider the lock acquired.

Release the lock on all nodes when done.

Timing is critical: for a 30‑second lock, the successful nodes should complete within a few milliseconds each; otherwise the lock is considered failed.

In practice, no locking mechanism can guarantee 100 % safety; therefore, applications should include compensation logic to handle rare inconsistencies.

JavaRedisDistributed LockLuaRedissonRedlockSETNX
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login 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.