Redis implements distributed lock tools that are often easy to use

Redis implements distributed lock tools that are often easy to use

public interface RedisDistributionLock {
   /** 
       * The lock is successful, and the lock time is returned 
       * @param lockKey 
       * @param threadName 
       * @return 
       */
      public long lock(String lockKey, String threadName); 
      
     /** 
       * To unlock, you need to update the lock time to determine whether you have permission 
       * @param lockKey 
       * @param lockValue 
       * @param threadName 
       */
      public void unlock(String lockKey, long lockValue, String threadName); 
      
     /** 
       * For multi-server clusters, use the following method instead of System.currentTimeMillis() to obtain the redis time to avoid time inconsistencies in multiple services! ! !
       * @return 
       */
      public long currtTimeForRedis(); 
}
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

public class RedisLockImpl implements RedisDistributionLock{
   //The lock timeout time, in milliseconds, that is: the operation is executed within the lock time, and if it is not completed, there will be a phenomenon 
      private static final long LOCK_TIMEOUT = 5*1000; 
      
      private static final Logger LOG = LoggerFactory.getLogger(RedisLockImpl.class); 
      
      private StringRedisTemplate redisTemplate; 
      
      public RedisLockImpl(StringRedisTemplate redisTemplate) { 
        this.redisTemplate = redisTemplate; 
      } 
      
     /** 
       * Locked 
       * Get the lock and lock, if you can't get the lock, wait until you get the lock 
       * @param lockKey 
       * @param threadName 
       * @return 
       */
      @Override
      public synchronized long lock(String lockKey, String threadName) { 
//LOG.info(threadName+"Start execution and lock"); 
        while (true){//Acquire the lock loop 
         //Lock time 
          Long lock_timeout = currtTimeForRedis()+ LOCK_TIMEOUT +1; 
          if (redisTemplate.execute(new RedisCallback<Boolean>() { 
            @Override
            public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException { 
             //Define the serialization method 
              RedisSerializer<String> serializer = redisTemplate.getStringSerializer(); 
              byte[] value = serializer.serialize(lock_timeout.toString()); 
              boolean flag = redisConnection.setNX(lockKey.getBytes(), value); 
              return flag; 
            } 
          })){ 
           //If the lock is successful 
//LOG.info(threadName + "lock successfully ++++ 111111"); 
           //Set the timeout time and release the memory 
            redisTemplate.expire(lockKey, LOCK_TIMEOUT, TimeUnit.MILLISECONDS); 
            return lock_timeout; 
          }else { 
           //Get the time in redis 
            String result = redisTemplate.opsForValue().get(lockKey); 
            Long currt_lock_timeout_str = result==null?null:Long.parseLong(result); 
           //The lock has expired 
            if (currt_lock_timeout_str != null && currt_lock_timeout_str <System.currentTimeMillis()){ 
             //Determine whether it is empty. When it is not empty, it means that it has failed. If the value is set by other threads, the second condition judgment cannot be executed 
             //Get the last lock expiration time and set the current lock expiration time 
              Long old_lock_timeout_Str = Long.valueOf(redisTemplate.opsForValue().getAndSet(lockKey, lock_timeout.toString())); 
              if (old_lock_timeout_Str != null && old_lock_timeout_Str.equals(currt_lock_timeout_str)){ 
               //When multiple threads are running, multiple threads are signed here, but only if the setting value of one thread is the same as the current value, it has the right to acquire the lock 
//LOG.info(threadName + "Successfully locked++++ 22222"); 
               //Set over time, release memory 
                redisTemplate.expire(lockKey, LOCK_TIMEOUT, TimeUnit.MILLISECONDS); 
      
               //Return to lock time 
                return lock_timeout; 
              } 
            } 
          } 
      
          try { 
//LOG.info(threadName + "Waiting to lock, sleep for 100 milliseconds"); 
//TimeUnit.MILLISECONDS.sleep(100); 
            TimeUnit.MILLISECONDS.sleep(200); 
          } catch (InterruptedException e) { 
            e.printStackTrace(); 
          } 
        } 
      } 
      
     /** 
       * Unlock 
       * @param lockKey 
       * @param lockValue 
       * @param threadName 
       */
      @Override
      public synchronized void unlock(String lockKey, long lockValue, String threadName) { 
        LOG.info(threadName + "execute unlock ==========");//Delete directly if it is abnormally closed, judge the lock and judge the expiration time 
       //Get the time set in redis 
        String result = redisTemplate.opsForValue().get(lockKey); 
        Long currt_lock_timeout_str = result ==null?null:Long.valueOf(result); 
      
       //If it is the locker, delete the lock, if not, wait for the automatic expiration and re-compete for the lock 
        if (currt_lock_timeout_str !=null && currt_lock_timeout_str == lockValue){ 
          redisTemplate.delete(lockKey); 
          LOG.info(threadName + "Unlocked successfully ------------------"); 
        } 
      } 
      
     /** 
       * For multi-server clusters, use the following method instead of System.currentTimeMillis() to obtain the redis time to avoid time inconsistencies in multiple services! ! !
       * @return 
       */
      @Override
      public long currtTimeForRedis(){ 
        return redisTemplate.execute(new RedisCallback<Long>() { 
          @Override
          public Long doInRedis(RedisConnection redisConnection) throws DataAccessException { 
            return redisConnection.time(); 
          } 
        }); 
      } 
}
//Create a redis distributed lock
private static final String LOCK_NO = "redis_distribution_lock_no1";

        RedisLockImpl redisLock = new RedisLockImpl(stringRedisTemplate);
       //lock time
        Long lockTime;
        String name = "uuid";
        if ((lockTime = redisLock.lock((LOCK_NO) + "", name)) != null) {
           //Business logic
            redisLock.unlock((LOCK_NO) + "", lockTime, name);
        }

Tools.

Reference: https://cloud.tencent.com/developer/article/1335863 redis implements distributed lock tools and is often easy to use