Redis implements distributed transaction lock

distributed lock

Distributed locks can actually be understood as: control the distributed system to operate on shared resources in an orderly manner, and maintain consistency through mutual exclusion. In layman's terms, there is only one pit in one toilet. I came first and locked it. Only after I leave and open the lock, you can go in, and then you lock it. And so on, to maintain consistency.

Realization principle

  • Mutual exclusion
    ensures that only one client can obtain the lock at the same time, that is, it can operate on shared resources
  • Security
    Only the locked service can have the unlocking authority, that is, the locks added by a cannot be unlocked by bcd. If they can be unlocked, the distributed locks are meaningless. The possible situation is that a goes to query and finds that the lock is held, and is preparing to unlock it
    .
  • Avoid deadlocks
    . Deadlocks will cause any subsequent services to lose locks, and no operations can be performed on shared resources.
  • Guarantee that locking and unlocking operations are atomic operations

Use redis to implement distributed locks

Use the redis command set key value NX EX (PX) max-lock-time to realize locking
Use the redis command EVAL to realize unlocking

lock

Jedis jedis = new Jedis("127.0.0.1", 6379);
 
 private static final String SUCCESS = "OK";
 
 
 
 /**
 
  * 加锁操作
 
  * @param key 锁标识
 
  * @param value 客户端标识
 
  * @param timeOut 过期时间
 
  */
 
 public Boolean lock(String key,String value,Long timeOut){
 
     String var1 = jedis.set(key,value,"NX","EX",timeOut);
 
     if(LOCK_SUCCESS.equals(var1)){
 
         return true;
 
     }
 
     return false;
 
 }

Interpretation:

Locking operation: jedis.set(key, value, "NX", "EX", timeOut) [guaranteed atomic operation of locking]

The key is the key value of redis as the identification of the lock, and the value is used as the identification of the client here. Only when the key-value is matched can you have the right to delete the lock [guaranteed security]

Set the expiration time through timeOut to ensure that there will be no deadlock [avoid deadlock]

What does NX (XX), EX (PX) mean?

NX: Only when the key does not exist, the operation will be performed, if not exists;

XX: Only when this key is saved, the operation will be performed, if exists;

EX: Set the expiration time of the key to seconds, and the specific time is determined by the fifth parameter

PX: units in milliseconds

unlock

Jedis jedis = new Jedis("127.0.0.1", 6379);
 
 private static final Long UNLOCK_SUCCESS = 1L;
 
 
 
 /**
 
  * 解锁操作
 
  * @param key 锁标识
 
  * @param value 客户端标识
 
  * @return
 
  */
 
 public static Boolean unLock(String key,String value){
 
     String luaScript = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else  return 0 end";
 
     Object var2 = jedis.eval(luaScript,Collections.singletonList(key), Collections.singletonList(value));
 
     if (UNLOCK_SUCCESS == var2) {
 
         return true;
 
     }
 
     return false;
 
 }

Interpretation:

luaScript This string is a lua script, which means that if the value obtained according to the key is the same as the value passed in, del will be executed, otherwise 0 will be returned [guaranteed security]

jedis.eval(String, list, list); This command is to execute the lua script, the set of KEYS is the second parameter, and the set of ARGV is the third parameter [atomic operation to ensure unlocking]

retry mechanism

The above only talked about the operation of locking and unlocking. Just imagine if you want to get the lock in the business. If you don’t get the lock, you should be blocked and wait or return directly. This problem can actually write a retry mechanism, and make a cycle to get the lock according to the number of retries and retry time. Of course, the number of retries and the appropriate time to set should be measured according to your own business

/**
 
 * 重试机制
 
 * @param key 锁标识
 
 * @param value 客户端标识
 
 * @param timeOut 过期时间
 
 * @param retry 重试次数
 
 * @param sleepTime 重试间隔时间
 
 * @return
 
 */
 
public Boolean lockRetry(String key,String value,Long timeOut,Integer retry,Long sleepTime){
 
    Boolean flag = false;
 
    try {
 
        for (int i=0;i<retry;i++){
 
            flag = lock(key,value,timeOut);
 
            if(flag){
 
                break;
 
            }
 
            Thread.sleep(sleepTime);
 
        }
 
    }catch (Exception e){
 
        e.printStackTrace();
 
    }
 
    return flag;
 
}

Detailed explanation of the set command in the text: http://redisdoc.com/string/set.html

Guess you like

Origin blog.csdn.net/weixin_43832604/article/details/106251566