Using redis distributed lock to solve the problem of concurrent thread resource sharing



As we all know, in multithreading, because sharing global variables will lead to inconsistent modification results of resources, it is necessary to lock to solve this problem, so as to ensure that only one thread operates on resources at the same time

But in the distributed architecture, our service may have n instances, but the thread lock is only valid for the same instance, so we need to use the distributed lock – redis setnx


When modifying a resource, set a key in redis, and value determines how to represent it according to the actual situation

Since we want to check whether the key exists (existence means that there are threads modifying resources, resources are locked, and other threads cannot operate at the same time. If the key does not exist, it means that resources are not occupied by threads, and threads are allowed to seize it. Then we will set vlaue through setnx to indicate that resources are locked, and other threads cannot operate at the same time)

The picture shows:


Our service is in a cluster. If we simply use thread lock to solve the above problems, there are problems: because threads are process based, two web servers are in different process spaces

In other words, if the request of user1 is sent to web Server1, it can only be locked with other requests of web Server1, but not affect the request of web server2

In the above figure, thread 1 is responsible for processing the request from user1 to web Server1, similarly thread 2 is responsible for processing the request from user2 to web server2

At the same time, 1, the two threads read the value of resume [u ticket] in MySQL as 100, which corresponds to the above figure (1) (2). Each thread performs – 1 operation on 100 and updates it to the database, which corresponds to (3) (4)

The expected situation is that the value of resume ﹐ ticket has been reduced twice, which should be 98. However, in reality, both threads have done 100-1 = 99 operations, and changed the value of Mysql to 99, which will lead to the inconsistency of the final data, so the distributed lock will be used.

Why redis?

Because redis is single threaded, there is no multi-threaded resource competition, and it is really fast

Why use setnx instead of set?

Setnx means that the key can only be set successfully if it does not exist, but set will modify the value if the key exists

Using the characteristics of setnx, we can design as follows:

Pseudo code:

#Set the redis lock
  redis key = 'residue_ticket_lock'

  #Get \
  def get_ticket():
    Time ﹐ out = 5 ﹐ in order to prevent the performance impact caused by too many threads, the current thread can't acquire the lock and is in the loop for a long time, we set a timeout. If the current thread hasn't preempted the distributed lock within the timeout, it will return the failed result
    while True:
       if redis.setnx('residue_ticket_lock','lock',5):
          #If setnx returns true, it means that there are no other threads operating the database at the moment, and the current thread can be locked successfully. Note that not only value = lock but also expiration time is set, which is necessary to prevent the locked thread from abnormally collapsing, resulting in the failure to release (delete key) and causing all other threads to never get the operation right
          Resume ﹐ ticket = mysql. Get ('resume ﹐ ticket ') ﹐ get the current remaining votes from MySQL
          Mysql. Update ('reserve  ticket ', reserve  ticket-1)  order succeeded, number of votes-1, update data to MySQL
          #Delete key, release lock
          return True
          #If setnx returns false, it indicates that there are other thread pairs operating. The current thread waits for 0.01s and continues the loop
          time_out -= 0.01
    return False

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.