Backend Development 11 min read

Implementing Distributed Locks with Redis: SETNX, Lua Scripts, Redisson, and RedLock

This article explains how to implement distributed locks in Redis using the SETNX command, atomic Lua scripts, the Redisson Java client, and the RedLock algorithm, providing code examples and discussing their advantages and limitations in distributed backend systems.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Implementing Distributed Locks with Redis: SETNX, Lua Scripts, Redisson, and RedLock

In distributed applications, controlling access to shared resources requires a distributed lock; single‑process mechanisms like synchronized are ineffective once the system is deployed across multiple nodes.

A common scenario is a cluster‑deployed scheduled task (e.g., Spring Quartz) that could be executed concurrently by several instances, leading to duplicate processing; a distributed lock ensures that only one instance performs the business logic at a time.

Redis offers several ways to implement a distributed lock. This article focuses on four approaches: the SETNX command, atomic Lua scripts, the Redisson Java client, and the RedLock algorithm.

SETNX syntax:

SETNX key value

It sets the key only if it does not exist, indicating a successful lock acquisition; otherwise the lock fails. However, a separate EXPIRE call is needed to set a timeout, which is not atomic. Since Redis 2.6.12 the SET command with options is preferred:

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

NX – set only if the key does not exist

XX – set only if the key already exists

EX – expiration time in seconds

PX – expiration time in milliseconds

Because SETNX + EXPIRE is not atomic, a Lua script can combine the two operations:

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

The corresponding unlock script:

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

Java implementation using these scripts:

package com.fullstack.commerce.user.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class RedisDistributeLock {
    private RedisClient jedis;
    private String key;
    private String value;
    private int expireTime; // milliseconds

    public RedisDistributeLock(RedisClient jedis, String key, String value, int expireTime) {
        this.jedis = jedis;
        this.key = key;
        this.value = value;
        this.expireTime = expireTime;
    }

    private static final String lock_script =
            "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 " +
            "    then" +
            "       redis.call('expire',KEYS[1],ARGV[2]) " +
            "       return 1 " +
            "    else" +
            "       return 0 " +
            "end";
    private static final String unlock_script =
            "if redis.call('get',KEYS[1]) == ARGV[1] then " +
            "    return redis.call('del',KEYS[1]) " +
            "else " +
            "    return 0 " +
            "end";

    /** * 加锁 */
    public boolean lock() {
        try {
            List
keys = new ArrayList<>();
            keys.add(key);
            List
args = Arrays.asList(value, String.valueOf(expireTime));
            Long result = (Long) jedis.eval(lock_script, keys, args);
            return result == 1L;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /** * 释放锁 */
    public boolean unlock() {
        List
keys = new ArrayList<>();
        keys.add(key);
        List
args = Arrays.asList(value, String.valueOf(expireTime));
        Long result = (Long) jedis.eval(unlock_script, keys, args);
        return result == 1L;
    }
}

Usage example:

RedisDistributeLock lock = new RedisDistributeLock(jedis, "mylock", "myclient", 2000);
if (lock.lock()) {
    try {
        System.out.println("加锁成功!");
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
} else {
    System.out.println("加锁失败!");
}
return "操作成功";

Redisson, a high‑level Redis Java client, simplifies lock handling. Maven dependency:

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

Configuration class:

package com.fullstack.commerce.user.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {
    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        return Redisson.create(config);
    }
}

Lock acquisition with Redisson:

RLock lock = redissonClient.getLock("fullstack_lock");
try {
    lock.tryLock(3, 30, TimeUnit.SECONDS);
    System.out.println("加锁成功!");
} catch (InterruptedException e) {
    throw new RuntimeException(e);
} finally {
    lock.unlock();
}
return "操作成功";

RedLock algorithm (proposed by antirez) addresses failure scenarios in Redis master‑slave setups by requiring a majority of independent master nodes to grant the lock. The steps include obtaining the current time in milliseconds, attempting to lock the same key/value on N instances within a short window, confirming that more than half of the instances succeeded and that the total acquisition time is less than the lock timeout, and finally adjusting the remaining timeout. If the lock cannot be obtained, all nodes attempt to release any partial locks. The algorithm has sparked debate among experts such as Martin Kleppmann.

In summary, Redis provides multiple viable solutions for distributed locking, with Redisson offering the most convenient API, while systems demanding strong consistency may prefer alternatives like Zookeeper.

backendJavaRedisDistributed LockluaRedisson
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

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.