Lock mechanism
Usually used in the lock is divided into optimistic lock, pessimistic lock two, a brief introduction of these two kinds of locks, as the background of this article, for this kind of knowledge has been enough to understand the students can skip this part.
Optimistic lock
First look at the Baidu Encyclopedia on the explanation: mostly based on the data version of the record mechanism implementation. What is a data version? is to add a version identity to the data, which is typically done by adding a "version" field to the database table in the version solution based on the database table. When the data is read, the version number is read together, and then the version number is added one after the update. At this point, the version data of the submitted data is compared to the current version information of the database table corresponding to the record, and if the submitted version number is greater than the current version number of the database table, it is updated, otherwise it is considered to be outdated data.
In fact, it is like a gym only a treadmill, at the door of the gym has a automatic arranging machine, every person into the gym must first get a number to enter, if someone on the treadmill, then do warm-up, drink water, if no one on the treadmill, Confirm that the number currently displayed on the treadmill (the number of the person who used the treadmill) is smaller than the one in hand, and if it is small, it can be used; otherwise, it means that the number is in the real world we all know either to go, or to rearrange, or not to queue, in the system is the same, usually return error.
Pessimistic lock
Similarly, look at the explanation of Baidu Encyclopedia: has a strong monopoly and exclusive characteristics. It refers to the conservative attitude to the data being modified by the outside world (including other transactions currently in the system, as well as transactions from external systems), so that the data is locked during the entire data processing process. Pessimistic lock implementation, often rely on the database provided by the lock mechanism (also only the database layer provides a lock mechanism to truly guarantee the exclusivity of data access, otherwise, even in this system to implement the locking mechanism, there is no guarantee that the external system will not modify the data).
Then, the same popular explanation, or the gym. This time in the doorway does not need to automatic arranging machine, but hang the key (only one), want to go in the person must get this key to go, get the key person can enter, whether it is warm-up, water or running can, until he came out to put the key back to the wall, the next can go to fight, to get in. Sounds like a bit impersonal, so pessimistic locking is more suitable for strong consistency scenes, but less efficient, especially read concurrency is low. Optimistic locking is suitable for scenes with less read-write and less concurrency conflicts.
Background
First of all, the development of this article background, easy to understand why to use pessimistic lock and the details of the lock design.
Task distribution System: There are a lot of tasks (articles) in the task Pool (MySQL), which now requires user assistance to edit, the basic requirements of the system are as follows (simplified version):
1, push the user interested in the classification under the task to the user editor;
2, the user editor to submit a task, automatically push the next task;
3, assign only one task to the user at a time;
4, if a user occupy a task more than a certain time, then automatically release tasks, tasks into the task pool, re-cycle;
5 、......
Goal
There are two goals:
1, a task in the same time period can only be held by one user;
2, to avoid the death of the task, that is to avoid the task by the user for a long time to occupy, unable to release.
Ideas
Because the system concurrency is large, and there are frequent write operations, so choose pessimistic lock to control each task can only be picked up by one user. The main ideas are as follows:
1, from the task pool to identify a portion of the task can be assigned;
2, according to a certain order, select a task, as a candidate push task;
3, try to lock the candidate push task;
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 picked up and repeated 2-5 until the push succeeds.
Realize
Only the implementation mechanism of the lock is described here, and the rest of the business logic is skipped. Since the locking process should be non-detachable, which is often said to be atomic, the setnx operation in Redis is chosen as a locking method.
The simplified version of the code is as follows:
function lock ( $strMutex, $intTimeout) {$ Objredis = new Redis (); //using setnx atomic operation plus lock $intRet = $ Objredis->setnx ( $strMutex, 1); if ( $intRet) {//set expiration Time, Prevention of death tasks $objRedis->expire ( $strMutex, $intTimeout); return true;} return false;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
The problem with this code is that setnx succeeds, but expire fails, and there may be a case of dead tasks. A common way to solve this problem is to use the INCR method instead of Setnx, as follows:
function Lock ($strMutex,$intTimeout,$intMaxTimes=0) {$objRedis=New Redis ();Lock with incr Atomic type operation$intRet=$objRedis->INCR ($strMutex);if ($intRet===1) {Set expiration time to prevent dead tasks from appearing$objRedis->expire ($strMutex,$intTimeout);return true;} if ( $intMaxTimes > 0 && $intRet >= $intMaxTimes && $ Objredis->ttl ( $strMutex) === Span class= "Hljs-subst" >-1) {//when the maximum number of locks is set Force unlock $objRedis ->del ( $strMutex); } return false;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
This code is $intmaxtimes to ensure that the system does not appear to be dead, even if the expire is unsuccessful.
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) { Span class= "hljs-variable" > $objRedis = new Redis (); //use SETNX operation plus lock, set expiration time $objRedis->set ( $strMutex, 1, $intTimeout, ' NX '); if ( $strRet = = = ' OK ') {return true;} return false;}
This method is what I think is the best now, but why not introduce this method directly, but introduce incr that method first? In fact, the careful classmate can see above that aspect has two bold word "general". The reason for this is that the set method only starts to support multiple parameters from the redis2.6.12 version.
The level is limited, welcome correction ~
If you want to forward, please indicate the source, thx~
Resources:
Http://redisdoc.com/string/set.html
Pessimistic locking with Redis (back-end language in PHP for example)