Redis is a popular open-source key-value database. At present, ruisi's background architecture adopts a combination of redis and MySQL on the database layer. redis is mainly used to store status information (such as the current seed peer) and read/write frequent data. Redis is fully running on the memory and has no lock design. It is very fast! According to the test, the read/write speed on the ruisi server reaches 30 thousand times/s. In highly concurrent applications, we often need to compete for some resources, for example, when many people download a popular resource, there may be many requests to modify the peer information of a resource (that is, to save the IP address and port number of the current Spector). When a request needs to modify the peer information, other requests cannot be modified. Otherwise, data overwrites may occur. However, redis does not provide data locking, so we need to implement it through the commands provided by redis: Idea 1: Using get and set commands to implement this method is easy to think, when each request arrives, get is used to determine whether the lock exists. If the lock does not exist, set is created. This method has one drawback. Because get and set are two redis requests, there is a latency between them. In a highly concurrent environment, it is possible that the lock has been set by another thread before the set after the get detects that the lock is not saved. Then, the current thread is set again, so that the lock will become invalid. Therefore, this method can only deal with a low concurrency. Train of Thought 2: Use the setnx and expire commands to set a lock key through the setnx command when accessing resources that require mutual access. The role of setnx is to determine whether the lock exists, if it does not exist, creation is successful. If it exists, failure is returned. The server returns the result to the client, indicating that the client will try again later. The expire command is used to set an expiration time for the lock, which is used to prevent the thread from crash, resulting in the lock being valid all the time, resulting in a deadlock. For example, if the lock validity period is set to 100 seconds, the lock will automatically expire after 100 seconds even if the thread crashes.
- > Setnx lock "Lock"
Copy code
If yes, set the expiration time.
- > Expire locks 100
Copy code
After the mutex resource is accessed, delete the lock.
- > Del lock
Copy code
Thought 3: using the transaction commands of watch and redis, the effect of this method is similar to that of thought 2. When the request arrives, watch and change the resource lock first. Then, by executing the lock creation process in the transaction, the lock key value can uniquely identify the request (for example, time + User ID ). If there are other threads requesting this resource, an error will be returned and re-tries will be returned when the lock is determined to exist (for example, ruisi BT tracker returns "server overload, this is the case when the "auto-retry" prompt is displayed ). If multiple requests judge that the modified lock does not exist and the lock is created at the same time, this will also cause the previous watch thread to fail to execute the transaction and return to the client for automatic retry. This eventually achieves the goal of locking.
Analysis on redis implementing lock mutex Resource Access