20 minutes to familiarize you with Redisson distributed lock design scheme

Posted by lunac on Tue, 01 Feb 2022 03:50:25 +0100

preface

   if you find it useful, remember to give the blogger a praise, comment and collection. It's not easy to write with one button.
   and it's said that people who praise won't have too bad luck every day. If it's really white whoring, you're welcome to come often!!!

20 minutes to familiarize you with Redisson distributed lock design scheme

01 revisit distributed lock

  distributed lock is also a kind of lock mechanism, which only appears to deal with the distributed environment,
It is not a new component or middleware, it is just a mechanism, an implementation, that is, a solution.
  it is used to ensure that in a distributed environment, multiple clients or service processes can access "shared resources" mutually exclusive through the locking mechanism, so as to avoid problems such as concurrency security and data inconsistency.

01:: 01 some requirements for the design of distributed lock

There are several general requirements in the industry:

  1. exclusiveness
  2. Avoid deadlock
  3. High availability
  4. Reentrant
  5. Fair lock (optional)

01:: 02 how to understand distributed locks?

  that is, to protect the safety problems caused by high-tech development through the atomic behavior of a third party.
  maybe this sentence is a little tongue twister for beginners. It doesn't matter. It will be helpful to write it down.

02 advantages of redisson distributed lock design

  Redisson distributed lock solves the defect of implementing distributed lock based on redis atomic operation.

02:: 01 deficiency of redis distributed lock design

  1. When performing Redis atomic operations, you need to set exhibit, that is, the TTL of the Redis key. The expiration time set in different business scenarios is different. If it is not set properly, it may affect the performance of the system and Redis services.
  2. The Redis atomic operation SETNX does not have the "reentrant" feature when acquiring distributed locks, that is, when a thread acquires a lock, other threads fail to acquire the lock, which is essentially OK. However, some business scenarios may require threads to have the "reentrant" feature. At this time, SETNX operation is not satisfied with the current needs, We need some supporting logic to deal with it, that is, the code of while(true) {}, but this method is not elegant, and it is likely to cause the risk of "jamming" of the application system.
  3. When Redis atomic operation is [after SETNX and before expir], the IDS service is down, and the key is not deleted due to problems in the application service, the resulting impact will eventually lead to deadlock threads, that is, no thread can obtain the lock of the key value (the lock without TTL is not deleted, resulting in its permanent existence).

03 Redisson distributed lock features

  1. Reentrant lock
  2. Fair lock
  3. interlocking
  4. Red lock
  5. Read write lock
  6. Semaphore and locking

04 Redisson distributed lock (reentrant lock) practice

  reentrant locks can be divided into one-time and reentrant locks. According to the meaning of the name, one-time means that if the current thread can obtain the distributed lock, if it succeeds, it will fail forever if it fails. Reentrant means that when the current thread does not obtain the distributed lock, it will not fail immediately, but wait for a period of time to obtain it again.

04::01 Redisson distributed lock (reentrant lock) one-time lock practice

The code is as follows:

    @Autowired
    private RedissonClient redissonClient;
    /**
     * Redission Distributed lock design (disposable lock)
     * */
    @ApiOperation(value = "Redission Distributed lock design(Disposable lock)",notes = "Redission Distributed lock design(Disposable lock)")
    @ResponseBody
    @PostMapping("/onelock")
    public ResponseBo onelock(String key)  {
        String msgValue = "onelock";
        long startTime = init(msgValue,key);
        //Distributed lock name
        final String lockName = "redissonOneLock-"+key;
        RLock lock = redissonClient.getLock(lockName);
        try{
            //Try to lock and unlock automatically 10 seconds after locking
            lock.lock(10,TimeUnit.SECONDS);
            this.info("One time distributed lock acquired");
            this.info("Execute business logic");
            endLog(msgValue,startTime);
            return ResponseBo.ok();
        }catch (Exception e){
            endLogError(msgValue,startTime,e);
            return ResponseBo.error("Save failed" + e.getMessage());
        }finally {
            /**
             * Note: release the lock after accessing the shared resources
             * */
            if (lock!= null){
                this.info("Release distributed lock");
                lock.unlock();
                //Note in some strict business scenarios, you can also call the method of forcibly releasing distributed locks
                //lock.forceUnlock();
            }
        }
    }

Test:

04::02 Redisson distributed lock (reentrant lock) reentrant lock practice

The code is as follows:

    @Autowired
    private RedissonClient redissonClient;
        /**
     * Redission Distributed lock design (reentrant lock)
     * */
    @ApiOperation(value = "Redission Distributed lock design(Reentrant lock)",notes = "Redission Distributed lock design(Reentrant lock)")
    @ResponseBody
    @PostMapping("/trylock")
    public ResponseBo trylock(String key)  {
        String msgValue = "trylock";
        long startTime = init(msgValue,key);
        //Distributed lock name
        final String lockName = "redissonTryLock-"+key;
        RLock lock = redissonClient.getLock(lockName);
        try{
           //Try to lock, wait up to 100 seconds, and unlock automatically 10 seconds after locking
            Boolean aBoolean = lock.tryLock(100,10,TimeUnit.SECONDS);
            if (aBoolean){
                this.info("Reentrant distributed lock obtained");
                this.info("Execute business logic");
            }
            endLog(msgValue,startTime);
            return ResponseBo.ok();
        }catch (Exception e){
            endLogError(msgValue,startTime,e);
            return ResponseBo.error("Save failed" + e.getMessage());
        }finally {
            /**
             * Note: release the lock after accessing the shared resources
             * */
            if (lock!= null){
                this.info("Release distributed lock");
                lock.unlock();
                //Note in some strict business scenarios, you can also call the method of forcibly releasing distributed locks
                //lock.forceUnlock();
            }
        }
    }

Test:

Topics: Java Redis Multithreading Distribution Middleware