SoFunction
Updated on 2025-04-16

Several implementation methods of Redis distributed lock

Redis basic command:

// Set the value of the key myKey to myValue, and the key expires after 10 secondsSET myKey myValue EX 10
// Set the value of the key myKey to myValue, and the key expires after 1000 milliseconds (1 second)SET myKey myValue PX 1000
// Specify the key expiration time, in seconds, and will be automatically deleted after expirationEXPIRE key_name second_num
// Specify the expiration time of the key, in milliseconds, and will be automatically deleted after expirationPEXPIRE key_name millisecond_num

// Return the key expiration timeTTL key_name 

SET key value	 //Set the value of the key key to valueSETNX key value	 //Only when the key key does not exist, set the value of the key to valueSETEX key seconds value	 //Set the value of the key key to value and the timeout is seconds secondsPSETEX key milliseconds value  //Set the value of the key key to value and the timeout is milliseconds milliseconds

1. Basic solution: SETNX command implementation

public class SimpleRedisLock {
    private Jedis jedis;
    private String lockKey;

    public SimpleRedisLock(Jedis jedis, String lockKey) {
         = jedis;
         = lockKey;
    }
    public boolean tryLock() {
        Long result = (lockKey, "locked");
        if (result == 1) {
            (lockKey, 30); // Set expiration time            return true;
        }
        return false;
    }
    public void unlock() {
        (lockKey);
    }
}

// Use exampleJedis jedis = new Jedis("localhost");
SimpleRedisLock lock = new SimpleRedisLock(jedis, "order_lock");
try{
    if(()){
    // Business logic    }
} finally {
    ();
}

Problem analysis:

  • Non-atomic operations: Setnx and Expire non-atomic operations may generate deadlocks
  • Lock error delete: Any client can delete the lock
  • No reentry: Repeated acquisition of the same thread will fail

2. Improvement plan: Atomic SET command

public class AtomicRedisLock {
    private Jedis jedis;
    private String lockKey;
    private String clientId;

    public SimpleRedisLock(Jedis jedis, String lockKey) {
         = jedis;
         = lockKey;
         = ().toString();
    }
    public boolean tryLock(int expireSeconds) {
        String result = (lockKey, clientId, ().nx().ex(expireSeconds));
        return "OK".equals(result);
    }
    public boolean unlock() {
        String script = "if ('get', KEYS[1]) == ARGV[1] then " +
                "return ('del', KEYS[1]) " +
                "else return 0 end";
        Object result = (script, (lockKey), (clientId));
        return (1L);
    }
}

// Use exampleJedis jedis = new Jedis("localhost");
AtomicRedisLock lock = new AtomicRedisLock(jedis, "payment_lock");
try{
    if((30)){
    // Business logic    }
} finally {
    ();
}

Core improvements:

  • Use the atomic SET command: SET key value NX EX
  • Lua scripts guarantee atomicity removal
  • Client unique identifier to prevent error deletion

Still existing problems:

  • Difficulty in renewing lock
  • Single point of failure risk
  • Business timeout may cause lock failure

3. High availability solution: RedLock algorithm

public class RedLock {
    pprivate List<Jedis> jedisList;
    private String lockKey;
    private String clientId;
    private int quorum;

    public RedLock(List<Jedis> jedisList, String lockKey) {
         = jedisList;
         = lockKey;
         = ().toString();
         = () / 2 + 1;
    }
    public boolean tryLock(int expireMillis) {
        long startTime = ();
        // Phase 1: Try to acquire most node locks        int successCount = 0;
        for (Jedis jedis : jedisList) {
            if (tryAcquire(jedis, expireMillis)) {
                successCount++;
            }
            if ((() - startTime) > expireMillis) {
                break;
            }
        }
        // Phase 2: Verify the validity of the lock        if (successCount >= quorum) {
            long validityTime = expireMillis - (() - startTime);
            return validityTime > 0;
        }
        // Stage 3: Release the acquired lock        for (Jedis jedis : jedisList) {
            release(jedis);
        }
        return false;
    }
    private boolean tryAcquire(Jedis jedis, long expireMillis) {
        try {
            String result = (lockKey, clientId, ().nx().px(expireMillis));
            return "OK".equals(result);
        } catch (Exception e) {
            return false;
        }
    }
    private void release(Jedis jedis) {
        String script = "if ('get', KEYS[1]) == ARGV[1] then " +
                "return ('del', KEYS[1]) else return 0 end";
        (script, (lockKey), (clientId));
    }
}

Deployment Requirements:

  • At least 5 independent Redis instances
  • Clock synchronization between nodes
  • A reasonable timeout is required

Applicable scenarios:

  • Scenarios with extremely high reliability requirements such as financial transactions
  • Distributed systems that require cross-computer room deployment

4. Production-level solution: Redisson implementation

// Configure the Redisson clientConfig config = new Config();
().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = (config);
// Acquire the lock objectRLock lock = ("orderLock");
try {
    // Try to add lock, wait for up to 100 seconds, and automatically unlock 30 seconds after locking    boolean isLock = (100, 30, );
    if (isLock) {
        // Handle business    }
} finally {
    ();
}

// Close the client();
// Automatic renewal mechanism (Watchdog), Watchdog implementation principle (simplified version)private void renewExpiration() {
    Timeout task = (() -> {
        if ((...)){ // Check if the lock is still held            expireAsync(); // Renewal            renewExpiration(); // Recursive call        }
    }, internalLockLeaseTime / 3, );
}

Core features:

  • Supports reentrant locks
  • Provides fair lock, interlock (MultiLock), and red lock (RedLock) implementation
  • Complete fault handling mechanism

This is the end of this article about several implementation methods of Redis distributed locks. For more related content on Redis distributed locks, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!