What is the proper use of distributed lock and redis implement a distributed lock What is the proper use of distributed lock and redis achieve Distributed Lock

 

turn:

What is the proper use of distributed lock and redis achieve Distributed Lock

 Distributed Lock

  Distributed Lock can actually be understood as: distributed control system ordered to operate on shared resources, to maintain consistency through mutually exclusive. For a very appropriate example: Suppose a shared resource is a house, there are all kinds of books, distributed systems is to come in person to read, distributed lock is to ensure that the house has only one door and only one person can enter , and the door only a key. Many people then go read a book, you can line up, the first person took the key and opened the door into the house and locked the door read, and then the second person is not the key, then waited out a ranking, then you take the key in, then so is

 The principle

  • Mutually exclusive

    • The same time ensure that only one client can get a lock, that can operate on shared resources

  • safety

    • Only unlock the locked service in order to have rights, that is, can not let a plus locks, bcd can be unlocked, if it can be distributed to unlock the lock on nothing meaningless

    • Situations that may arise is a lock to hold the inquiry found, just ready to unlock, this time suddenly held a lock expired, then b to get a lock, because a lock expired, b to get a lock, this time a continue the second step to unlock if we do not check, it will b held by the lock gave deleted

  • Avoid deadlock

    • Deadlock will lead to follow-up any services that get locked and can no longer carry out any operation on a shared resource

  • To ensure locking and unlocking operations are atomic operations

    • In fact, this is part of the problem to achieve distributed lock, assuming a realization distributed lock with redis
    • Suppose locking operation, a two-step procedure:

    • 1, a key set (key, value) 2, to set an expiration time key

    • Suppose now realize after just a set, the program has led to the collapse did not give the key to set the expiration time has led to key there has been a deadlock occurs

 How to implement a distributed lock

  Way to achieve distributed lock There are many, as long as the above conditions can be achieved distributed lock, such as a database, redis, zookeeper, where it will speak about how to implement a distributed lock redis

 Redis achieved using a distributed lock

  • Use redis command set key value NX EX max-lock-time to achieve locking

  • Use redis command EVAL unlocking

 

Lock:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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) [atomic operations to ensure the lock]

  • key is the key value as a lock redis identity, value here as the identity of the client, with only the key-value than the right to delete only guarantee the safety lock []

  • By timeOut set the expiration time to ensure that no deadlock deadlock avoidance []

  • NX, EX What does it mean?

    • NX: only this key does not exist when it will be operated, if not exists;

    • EX: set the key expiration time in seconds, the time is determined by the specific parameters 5


Unlock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 ;
 
  }

解读:

  • luaScript 这个字符串是个lua脚本,代表的意思是如果根据key拿到的value跟传入的value相同就执行del,否则就返回0【保证安全性】

  • jedis.eval(String,list,list);这个命令就是去执行lua脚本,KEYS的集合就是第二个参数,ARGV的集合就是第三参数【保证解锁的原子操作】

上述就实现了怎么使用redis去正确的实现分布式锁,但是有个小缺陷就是锁过期时间要设置为多少合适,这个其实还是需要去根据业务场景考量一下的


  上面那只是讲了加锁与解锁的操作,试想一下如果在业务中去拿锁如果没有拿到是应该阻塞着一直等待还是直接返回,这个问题其实可以写一个重试机制,根据重试次数和重试时间做一个循环去拿锁,当然这个重试的次数和时间设多少合适,是需要根据自身业务去衡量的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 
  * 重试机制
 
  * @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;
 
}

  

到这,用redis实现分布式锁就写完了,下次用zookeeper去实现分布式锁,欢迎留言吐槽 txtx

 

文中set命令详解:http://redisdoc.com/string/set.html

Guess you like

Origin www.cnblogs.com/libin6505/p/11031945.html