SpringBoot integrates Redisson to realize Redis cluster distributed lock

Posted by waq2062 on Thu, 10 Feb 2022 05:51:34 +0100

Distributed lock usage scenario

Protect shared resources with locks, such as generating a unique serial number, ensuring sufficient inventory before placing an order in the e-commerce system, etc.

The core principle of RedLock algorithm:

N Redis master nodes that are completely independent and have no master-slave relationship are used to ensure that they will not go down at the same time in most cases. N is generally odd. A client needs to do the following to obtain a lock:

  1. Gets the current time in milliseconds.
  2. Use the same key and random value to request locks on N nodes in turn. In this step, when the client requests locks on each master, there will be a much smaller timeout than the total lock release time. For example, if the automatic lock release time is 10 seconds, the timeout time of lock request of each node may be in the range of 5-50 milliseconds, which can prevent a client from blocking a failed master node for a long time. If a master node is unavailable, we should try the next master node as soon as possible.
  3. The client calculates the time spent in acquiring the lock in the second step. Only when the client successfully acquires the lock ((N/2) +1) on most master nodes and the total time consumed does not exceed the lock release time, the lock is considered to have been successfully acquired.
  4. If the lock is obtained successfully, the automatic lock release time is the initial lock release time minus the time consumed to obtain the lock before.
  5. If the lock acquisition fails, the client will release the lock on each master node, even those locks that he thinks have not been acquired successfully, whether it is because less than half of the successfully acquired locks (N/2+1) or because the total time consumed exceeds the lock release time.

To put it simply, it means using multiple master nodes to obtain locks at more than half of the master nodes; Otherwise, it will fail and roll back – delete the locks acquired on all nodes before.

Source code

Maven dependency







  port: 8091
    address:,, # Redis cluster address
    try-time: 0   #Try time
    lock-time: 4  #Lock time
    password:     # redis password
    scanInterval: 1000 # Scan interval
    retryAttempts: 5   # Command failure retries
    timeout: 3000    # Timeout

Redistribution configuration class

public class RedissonConfig {

    @Value(value = "${spring.redisson.address}")
    private String redissonAddress;

    @Value(value = "${spring.redisson.password}")
    private String redissonPassword;

    @Value(value = "${spring.redisson.scanInterval}")
    private int redissonScanInterval;

    @Value(value = "${spring.redisson.retryAttempts}")
    private int redissonRetryAttempts;

    @Value(value = "${spring.redisson.timeout}")
    private int redissonTimeout;

    public RedissonClient redissonClient() {
        String[] nodes = redissonAddress.split(",");
        for (int i = 0; i < nodes.length; i++) {
            nodes[i] = "redis://" + nodes[i];

        Config config = new Config();
        config.useClusterServers() //This is the cluster server used
                .setScanInterval(redissonScanInterval) //Set cluster status scanning time
        if (StringUtils.isNotEmpty(redissonPassword)) {
        return Redisson.create(config);

Controller test class

@RequestMapping("api/redisson" )
public class RedissonLockController {

     * Lock test shared variable
    private Integer lockCount = 10;

     * Lock free test shared variable
    private Integer count = 10;

     * Number of simulated threads

    private static int threadNum = 1000;

    private RedissonClient redissonClient;

     * Simulate concurrent testing with and without locks
     * @return
    public void lock(){
        // Counter
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        for (int i = 0; i < threadNum; i ++) {
            MyRunnable myRunnable = new MyRunnable(countDownLatch);
            Thread myThread = new Thread(myRunnable);
        // Free all threads

     * Lock test
    private void testLockCount() {
        RLock lock = redissonClient.getLock("myLock");
        try {
            // Lock, set the timeout of 2s, and unlock automatically 10 seconds after locking
            boolean getLock = lock.tryLock(2000,10000, TimeUnit.MILLISECONDS);
            if (!getLock) {
                log.info("Current thread:[{}]No lock obtained", Thread.currentThread().getName());
                return ;
            log.info("lockCount Value:"+lockCount);
        }catch (Exception e){
        }finally {
            // Release lock
            if(null != lock && lock.isLocked() && lock.isHeldByCurrentThread()){

     * Lockless test
    private void testCount() {
        log.info("count Value:"+count);

    public class MyRunnable implements Runnable {
         * Counter
        final CountDownLatch countDownLatch;
        public MyRunnable(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;

        public void run() {
            try {
                // Block the current thread until the timer value is 0
            } catch (InterruptedException e) {
            // Lockless operation
            // Locking operation

RedisLockApplication startup class

public class RedisLockApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisLockApplication.class, args);


Access: http://localhost:8091/api/redisson/test , the console outputs the synchronized serial number as follows:


reference resources






Source code

Topics: Spring Boot