Home  >  Article  >  Backend Development  >  Analysis of pessimistic locking mechanism implemented by PHP and redis

Analysis of pessimistic locking mechanism implemented by PHP and redis

不言
不言Original
2018-06-12 16:32:542429browse

This article mainly introduces the pessimistic lock mechanism implemented by PHP redis, briefly introduces the redis lock mechanism, optimistic lock, pessimistic lock and other concepts, and analyzes the related operating techniques of pessimistic lock implemented by PHP redis in the form of examples. Friends in need You can refer to the following

The example of this article describes the pessimistic lock implemented by PHP redis. Share it with everyone for your reference, the details are as follows:

Lock mechanism

The commonly used locks are divided into optimistic locks and pessimistic locks. , a brief introduction to these two types of locks is provided as the background knowledge of this article. Students who already have sufficient knowledge of this type of knowledge can skip this part.

Optimistic Lock

Let’s first look at the explanation on Baidu Encyclopedia: Most of them are based on the data version (Version) recording mechanism. . What is a data version? That is to add a version identifier to the data. In version solutions based on database tables, this is usually achieved by adding a "version" field to the database table. When the data is read out, this version number is also read out, and when it is updated later, this version number is incremented by one. At this time, the version data of the submitted data is compared with the current version information of the corresponding record in the database table. If the version number of the submitted data is greater than the current version number of the database table, it will be updated, otherwise it will be considered as expired data.

In fact, to put it bluntly, it is like there is only one treadmill in a gym, and there is a numbering machine at the entrance of the gym. Everyone who enters the gym must get a number before entering. If you are running If there is someone on the treadmill, warm up and drink water. If there is no one on the treadmill, confirm whether the number currently displayed on the treadmill (the number of the last person who used the treadmill) is smaller than the one you are holding. If it is smaller, can be used; otherwise, it means that the number has been passed. In reality, we all know that we have to either leave or rearrange, but we cannot jump in the queue. The same is true in the system, and an error is usually returned.

Pessimistic Lock

Similarly, let’s take a look at Baidu Encyclopedia’s explanation: It has strong exclusive and exclusive characteristics. It refers to a conservative attitude towards data being modified by the outside world (including other current transactions of the system and transaction processing from external systems). Therefore, the data is kept in a locked state during the entire data processing process. The implementation of pessimistic locking often relies on the locking mechanism provided by the database (only the locking mechanism provided by the database layer can truly guarantee the exclusivity of data access. Otherwise, even if the locking mechanism is implemented in this system, there is no guarantee that the external system will not modify it. data).

Then, in the same popular explanation, it is still the gym. This time, there is no need for a queuing machine at the door. Instead, there is a key (only one). People who want to enter must get this key. Those who get the key can enter, whether it is to warm up or drink water. You can still run, until he comes out and hangs the key back on the wall, you can fight for the next one, and only after you get it can you go in again. It sounds a bit inhumane, so Pessimistic locking is more suitable for strong consistency scenarios, but the efficiency is relatively low, especially the read concurrency is low. Optimistic locking is suitable for scenarios with more reads and less writes and fewer concurrency conflicts.

Background

Let me first talk about the development background of this article, so that everyone can understand why pessimistic locking is used and what is in the article Detailed design of lock.

Task distribution system: There are a large number of tasks (articles) in the task pool (mysql), and now users are required to assist in editing. The basic requirements of the system are as follows (simplified version):

1. Push users who are interested tasks under the category to the user editor;
2. After the user edits and submits a task, the next task will be automatically pushed;
3. Only one task is assigned to the user at a time;
4. If a If the user occupies a task for more than a certain period of time, the task will be automatically released and the task will be entered into the task pool and recirculated;
5,...

Goal

There are two goals:

1. A task can only be held by one user at the same time;

2. Avoid dead tasks, that is, avoid tasks being held by users Possessed for a long time and cannot be released.

Ideas

Due to the large amount of system concurrency and frequent write operations, choosing pessimistic locking to control each task can only Received by one user at the same time. The main ideas are as follows:

1. Find some assignable tasks from the task pool;
2. Select a task according to a certain order as a candidate push task;
3. Try to match the candidates Push the task to lock;
4. If the lock is successful, push the task to the user, and modify the corresponding task status and user status;
5. If the lock fails, the task has been claimed, repeat 2- 5, until the push is successful.

accomplish

Only the implementation mechanism of locking is introduced here, and the rest of the business logic is skipped. Since the locking process should not be disassembled, which is often called an atomic operation, the setnx operation in redis is chosen as the locking method.

The simplified version of the code is as follows:

function lock($strMutex, $intTimeout) {
  $objRedis = new Redis();
  //使用setnx原子型操作加锁
  $intRet  = $objRedis->setnx($strMutex, 1);
  if ($intRet) {
    //设置过期时间,防止死任务的出现
    $objRedis->expire($strMutex, $intTimeout);
    return true;
  }
  return false;
}

There is a problem with this code, that is, setnx succeeds, but expire fails, which may exist Dead mission situation. A common way to solve this problem is by using the incr method instead of setnx, as follows:

function lock($strMutex, $intTimeout, $intMaxTimes = 0) {
  $objRedis = new Redis();
  //使用incr原子型操作加锁
  $intRet  = $objRedis->incr($strMutex);
  if ($intRet === 1) {
    //设置过期时间,防止死任务的出现
    $objRedis->expire($strMutex, $intTimeout);
    return true;
  }
  if ($intMaxTimes > 0 && $intRet >= $intMaxTimes && $objRedis->ttl($strMutex) === -1) {
    //当设置了最大加锁次数时,如果尝试加锁次数大于最大加锁次数并且无过期时间则强制解锁
    $objRedis->del($strMutex);
  }
  return false;
}

This code passes $intMaxTimes To ensure that even when expire is unsuccessful, it can be forced to unlock and ensure that there will be no dead tasks in the system.

Is there a better way?

In fact, the set operation in redis is compatible with setnx and supports setting the expiration time.

function lock($strMutex, $intTimeout) {
  $objRedis = new Redis();
  //使用setnx操作加锁,同时设置过期时间
  $strRet  = $objRedis->set($strMutex, 1, 'ex', $intTimeout, 'nx');
  if ($strRet === 'OK') {
    return true;
  }
  return false;
}

This method is what I think is the best at present, but why is this method not introduced directly, but the incr method is introduced first? In fact, careful students can see that there are two bold words "general" in the above aspect. The reason why I say this is because the set method only supports multiple parameters from the redis2.6.12 version.

The level is limited, corrections are welcome~

The above is the entire content of this article. I hope it will be helpful to everyone's learning. For more related content, please pay attention to the PHP Chinese website!

Related recommendations:

Summary of the use of variable functions in php

Methods to implement PHP trees non-recursively

How to use PHP to obtain the real IP of the user client

##

The above is the detailed content of Analysis of pessimistic locking mechanism implemented by PHP and redis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn