An article about Redis distributed locks

Redis distributed lock

What is a distributed lock?

​ Redis distributed lock is a lock mechanism based on redis, which is used to control concurrent access to shared resources in a multi-concurrent distributed environment . When multiple applications or processes access a shared resource, the distributed lock can ensure that only one process can access the resource , and data inconsistency and race conditions will not occur.

Why do you need distributed locks?

​ In a multi-threaded environment, if multiple threads access shared resources at the same time, such as takeaway orders and product inventory, data competition will occur, resulting in dirty data or oversold products.

For example, suppose there are 100 users participating in a limited-time flash sale activity, and each user is limited to purchase 1 item, and the number of items is only 3. Without mutual exclusive access to shared resources, the following situations may occur:

  • Multiple threads, such as thread 1, 2, and 3, enter the buying method at the same time, and each thread corresponds to a user.
  • Thread 1 queries the quantity that the user has snapped up, and finds that the current user has not snapped up and there is still one product in stock, so it thinks that the snap-up process can continue.
  • Thread 2 also executes the query of the quantity that the user has snapped up, and finds that the current user has not snapped up and there is still 1 product in stock, so it thinks that the snap-up process can continue.
  • Thread 1 continues, decrements the stock quantity by 1, and returns success.
  • Thread 2 continues execution, decrements the inventory quantity by 1, and returns success.
  • At this time, the oversold problem occurred, resulting in an extra copy of the product being sold.

insert image description here

In order to ensure that shared resources are accessed safely, we need to use mutual exclusion operations to protect shared resources, that is, only one thread is allowed to access shared resources at a time, and other threads need to wait for the current thread to be released before accessing. In this way, data races and dirty data problems can be avoided, and the correctness and stability of the program can be guaranteed.

How can mutual exclusive access to shared resources be achieved? Locking is a more general solution, more precisely pessimistic locking.

Pessimistic locking always assumes the worst case, thinking that there will be problems every time a shared resource is accessed (for example, shared data is modified), so it will be locked every time it acquires a resource operation, so that other threads want to get this resource. It will block until the lock is released by the previous holder. That is to say, shared resources are only used by one thread at a time, other threads are blocked, and the resources are transferred to other threads after use .

For stand-alone multithreading, in Java, we usually use the native locks of JDK such as ReetrantLockclasses and keywords to control the access of multiple threads in a JVM process to local shared resources.synchronized

insert image description here

It can be seen from the figure that these threads access shared resources are mutually exclusive, and only one thread can acquire a local lock to access shared resources at the same time.

In a distributed system, different services/clients usually run on separate JVM processes. If multiple JVM processes share the same resource, there is no way to achieve mutually exclusive access to resources using local locks. Thus, distributed locks were born.

The figure below shows the situation of adding local locks in a distributed system.
insert image description here

At this time, because the sychornized lock is implemented based on the JVM, but each server has its own JVM, so sychornized cannot control multiple threads at this time.

The following figure shows the use of distributed locks.

insert image description here

​ When I was reading this part, I saw that someone mentioned in the barrage that distributed locks are to allow multiple jvm virtual machines to compete for the same lock. I think distributed locks are easy to understand if you think about it this way.

What conditions should distributed locks have?

A basic distributed lock needs to meet:

  • Mutual exclusion : At any one time, the lock can only be held by one thread.
  • High availability : The lock service is highly available. When a lock service fails, it can automatically switch to another lock service. Moreover, even if there is a problem with the code logic of the client's release lock, the lock will eventually be released, which will not affect other threads' access to shared resources. This is generally achieved through a timeout mechanism.
  • Reentrant : After a node acquires the lock, it can acquire the lock again.

In addition to the above three basic conditions, a good distributed lock also needs to meet the following conditions:

  • High performance : The operation of acquiring and releasing locks should be completed quickly and should not have a large impact on the performance of the entire system.
  • Non-blocking : If the lock cannot be obtained, it cannot wait indefinitely to avoid affecting the normal operation of the system.

Implementation of distributed locks

Redis implements distributed locks mainly by using the setnx command of Redis. setnx is SET IF NOT EXISTS (create if not exists).

  • acquire lock

    #添加锁  NX是互斥  EX是设置超时时间
    SET lock value NX EX 10
    
  • release lock

    DEL lock
    

insert image description here

How Redis implements distributed locks to control the effective duration

1. Estimate based on business execution time (generally not used, inaccurate).

2. Set an expiration time for the lock, and renew it after the business exceeds the expiration time.

How to proceed with renewal?

Redisson is an open source java language Redis client that provides many out-of-the-box functions.

Redisson provides a watch dog (watchdog) mechanism. If the thread that operates the shared data does not complete the business within the expiration time, Watch Dog will continue to extend the lock acquisition time. This ensures that the lock will not be released due to a timeout.
insert image description here

​ In general lock operations, we generally set that when a lock is acquired by a thread, if another thread wants to acquire the lock, it will interrupt the thread so that he cannot acquire the lock. However, a waiting mechanism is provided in redisson, which is the while loop in the above figure. After the lock is acquired, another thread continuously tries to acquire the lock, so that if thread 1 completes the business in a short period of time, thread 2 can execute the business immediately after acquiring the lock in a loop at this time, reducing the waiting time and improving the efficiency of business execution.

Is Redisson's implementation of distributed locks reentrant?

​Redisson implements distributed locks that are reentrant. The so-called reentrant lock means that the same lock can be acquired multiple times in a thread. For example, a thread is executing a method with a lock, and another method that requires the same lock is called in the method. Then the thread can directly execute the called method to re-enter without reacquiring the lock. like in Java synchronized``ReentrantLock.

​ The reentrant principle of redisson distributed lock is that it maintains a hash structure internally.

public void add1(){
    
    
RLock lock = redissonClient.getLock(“heimalock"); 
boolean isLock = lock.tryLock();
//执行业务
add2(); 
//释放锁
lock.unlock();
}
public void add2(){
    
    
RLock lock = redissonClient.getLock(“heimalock");
boolean isLock = lock.tryLock();
//执行业务
//释放锁
lock.unlock();
}

insert image description here

Summarize

  • How to implement Redis distributed lock?

    In Redis, you can use the SET command combined with the NX (SET IF NOT EXISTS) option to implement distributed locks. Here are the basic implementation steps:

    1. Acquiring a lock: When a process needs to acquire a lock, it sends a SET command to Redis, sets a specific key as the identity of the lock, and sets the expiration time. The key parameters are as follows:

      • The key name of the lock: usually a unique identifier used to identify the lock.
      • Lock value: can be a randomly generated unique value used to distinguish different processes.
      • Expiration time: Ensure that even if the lock is not explicitly released, it will automatically expire after a certain period of time to avoid deadlocks.

      For example, acquire a lock with:

      #添加锁  NX是互斥  EX是设置超时时间
      SET lock value NX EX 10
      

      If the key does not exist, that is, the lock has not been occupied by other processes, the lock is successfully acquired and OK is returned; if the key exists, the lock is already occupied by other processes, and the lock acquisition fails, returning nil.

    2. Release lock: When a process finishes operating on a shared resource, it needs to release the lock to allow other processes to acquire the lock. The process of releasing a lock consists of the following two steps:

      • Delete lock: The process deletes the key of the lock and releases the lock resource by executing the DEL command
      DEL lock
      
  • How to use Redis to realize the effective duration of the lock?

    The Redisson framework in Redis is used. Redisson needs to manually lock. You can set the lock expiration time and waiting time. When a business exceeds the lock expiration time, a Watch Dog watchdog mechanism is introduced in Redisson. It will check whether the business still holds the lock at regular intervals. If it still holds the lock, increase the holding time of the lock, and release the lock when the business is completed.

    In general lock operations, we generally set that when a lock is acquired by a thread, if another thread wants to acquire the lock, it will interrupt the thread so that he cannot acquire the lock. However, a waiting machine is provided in redisson. After the lock is acquired, another thread continuously tries to acquire the lock, so that if thread 1 completes the business in a short period of time, thread 2 can execute the business immediately after acquiring the lock in a loop at this time, reducing the waiting time and improving the efficiency of business execution.

  • Is the reentrant lock implemented by Redisson a reentrant lock?

    It is reentrant. The reentrant principle of redisson distributed lock is that it maintains a hash structure inside. Determine whether it is a lock held by the current thread, if so, count the locks held by the current thread, and decrement the value in the hash structure by one if the lock is released.

Most of the pictures in this article are from the dark horse ppt, which are borrowed here. Redis articles-10-redis distributed lock-implementation principle (setnx, redisson)_哔哩哔哩_bilibili

Guess you like

Origin blog.csdn.net/weixin_52340450/article/details/131708576