当前位置:网站首页>Redis distributed lock principle and its implementation with PHP (1)
Redis distributed lock principle and its implementation with PHP (1)
2022-07-05 15:05:00 【Back end regular developers】
List of articles
One 、 The role of distributed locks :
redis Write without locking function , To prevent multiple processes from performing an operation at the same time , Unexpected results ,so… Customize the locking function when inserting and updating the cache .
Two 、Redis Of NX Suffix command
Redis There's a series of orders , It is characterized by NX ending ,NX It can be understood as NOT EXISTS( non-existent ),SETNX command (SET IF NOT EXISTS) It can be understood that if it does not exist, insert ,Redis The implementation of distributed locks mainly uses SETNX command .
3、 ... and 、 Realization principle
Judge before the process requests to perform an operation , Whether the locking is successful , Successful locking allows the next operation ;
If it doesn't work , Then judge the value of the lock ( Time stamp ) Is greater than the current time , If greater than the current time , Then the lock acquisition fails, and the next operation is not allowed ;
If the value of the lock ( Time stamp ) Less than the current time , also GETSET The old value of the lock obtained by the command is still less than the current time , If the lock is obtained successfully, the next operation is allowed ;
If the value of the lock ( Time stamp ) Less than the current time , also GETSET The old value of the lock obtained by the command is greater than the current time , Then the lock acquisition fails, and the next operation is not allowed ;
Four 、$redis->setnx() Set lock
$expire = 10;// The period of validity 10 second
$key = 'lock';//key
$value = time() + $expire;// Value of lock = Unix Time stamp + The validity of the lock
$lock = $redis->setnx($key, $value);
// Judge whether the lock is successful , If successful, perform the next operation
if(!empty($lock))
{
// Next operation ...
}
If you return 1 , It means that the current process obtains the lock , And get the current insert / Update cached operation permissions .
If you return 0, Indicates that the lock has been acquired by another process , This is a process that can return results or wait for the current lock to fail before requesting .
5、 ... and 、 Solve the deadlock
If only SETNX Command to set the lock , If the process holding the lock crashes or the deletion of the lock fails , Other processes will not be able to acquire locks , It's a big problem .
The solution is to obtain the value of the lock while obtaining the lock fails , And compare the value with the current time , If the value is less than the current time, the lock will expire , The process can be applied Redis Of DEL Command to delete the lock .
$expire = 10;// The period of validity 10 second
$key = 'lock';//key
$value = time() + $expire;// Value of lock = Unix Time stamp + The validity of the lock
$status = true;
while($status)
{
$lock = $redis->setnx($key, $value);
if(empty($lock))
{
$value = $redis->get($key);
if($value < time())
{
$redis->del($key);
}
}else{
$status = false;
// Next operation ....
}
}
however , Use... Simply and roughly DEL Command to delete the lock again SETNX Command locking can also cause problems . such as , process 1 Crash after obtaining lock or failed to delete lock , And then the process 2 A lock is detected when it has expired , use DEL Command to delete the lock and use SETNX Command set lock , process 3 Lock expiration was also detected , Also used DEL The command delete lock is also used SETNX The command sets the lock , And then the process 2 And processes 3 The lock is also obtained . It's a big problem !
To solve this problem , It's used here Redis Of GETSET command ,GETSET The command returns the old value of the lock while setting a new value for the lock , So this is taking advantage of GETSET Command to get and assign properties at the same time , During this period, other processes cannot modify the value of the lock .
for example :
process 1 The operation timed out after obtaining the lock / collapse / Failed to delete lock ,
process 2 Detected that the lock already exists , However, the value of the lock obtained is compared with the current time, and it is found that the lock has expired ,
process 2 adopt GETSET The command assigns a new value to the lock , And get the old value of the lock , Compare the old value of the lock with the current time again , If the old value of the lock is still less than the current time , And then the process 2 You can ignore the process 1 I left the waste lock for the next operation .
process 2 After completing the next operation, you should delete the lock before returning , However, when deleting a lock, you can first check whether the lock has not expired , Delete before expiration , There is no need to delete locks that have expired , Because it is very likely that other processes have gone to acquire the lock when they detect that the lock has expired .
The point here is , If there are other processes in the process 2 Lock acquired before , So the process 2 Will fail to acquire the lock , But the process 2 In use GETSET When getting the old value of the lock, the lock is also given a new value , Rewrites the timeout value given to the lock by other processes . Seeing this, you may have questions , process 2 How can you change the value of a lock without obtaining it ? Yes , process 2 Changed the original value of the lock , But the impact of this small time error can be ignored .
Here are Redis Realize the integrity of distributed locks PHP Code :
<?php
/** * Realization Redis Distribution of the lock */
$key = 'test'; // To update the cache of information KEY
$lockKey = 'lock:'.$key; // Set lock KEY
$lockExpire = 10; // Set the validity of the lock to 10 second
// Get cache information
$result = $redis->get($key);
// Determine whether there is data in the cache
if(empty($result))
{
$status = TRUE;
while ($status)
{
// Set the lock value to the current timestamp + The period of validity
$lockValue = time() + $lockExpire;
/** * Create a lock * Try to use $lockKey by key Create a cache ,value The value is the current timestamp * because setnx() The function only exists when it does not exist key Cache will be created successfully * therefore , This function can be used to determine whether the current operation has been executed by other processes * @var [type] */
$lock = $redis->setnx($lockKey, $lockValue);
/** * The operation can be carried out when one of the two conditions is met * 1、 The lock was created successfully in the previous step ; * 2、 1) Judge the value of the lock ( Time stamp ) Whether it is less than the current time $redis->get() * 2) At the same time, set a new value for the lock successfully $redis->getset() */
if(!empty($lock) || ($redis->get($lockKey) < time() && $redis->getSet($lockKey, $lockValue) < time() ))
{
// Set the lifetime of the lock
$redis->expire($lockKey, $lockExpire);
//******************************
// Insert here 、 Update cache operation ...
//******************************
// Delete the lock after the above procedure
// Check whether the lock has expired , There is no need to delete expired locks
if($redis->ttl($lockKey))
$redis->del($lockKey);
$status = FALSE;
}else{
/** * If there is a valid lock, handle it accordingly * Wait for the current operation to complete before executing this request * Go straight back to */
sleep(2);// wait for 2 Try the operation again in seconds
}
}
}
Used to implement distributed locks Redis Command Introduction :
setnx(key, value)
take key The value of the set value, If and only if key non-existent .
If a given key Already exist , be SETNX Don't do anything .
SETNX yes ”SET if Not eXists”( If it doesn't exist , be SET) Abbreviation .
Return value :
Set up the success , return 1.
Setup failed , return 0.
get(key)
return key The string value associated .
If key If it does not exist, it returns a special value nil.
If key The stored value is not of string type , Return an error , because GET Can only be used to process string values .
Return value :
key Value .
If key non-existent , return nil.
getset(key, value)
Will be given key The value of the set value, And back to key The old value .
When key When it exists but is not a string type , Return an error .
Return value :
Return to a given key The old value (old value).
When key When there is no old value , return nil.
expire(key, seconds)
For a given key Set the lifetime .
When key expires , It will be automatically deleted .
stay Redis in , With time to live key It's called “ Volatile ”(volatile).
Below 2.1.3 Version of Redis in , The existing lifetime cannot be overwritten .
from 2.1.3 Version start ,key The lifetime of can be updated , Can also be PERSIST Command to remove .( For details, see http://redis.io/topics/expire).
Return value :
Set successfully returned 1.
When key Does not exist or cannot be for key When setting the lifetime ( For example, below 2.1.3 You try to update key Survival time ), return 0.
ttl(key)
Return to a given key The remaining lifetime of (time to live)( In seconds ).
Return value :
key The remaining lifetime of ( In seconds ).
When key When the lifetime does not exist or is not set , return -1 .
del(key)
Remove the given one or more key.
Return value :
Removed key The number of .
from :https://zhuanlan.zhihu.com/p/363418902
边栏推荐
- qt creater断点调试程序详解
- Your childhood happiness was contracted by it
- Mongdb learning notes
- Type declaration of all DOM elements in TS
- 美团优选管理层变动:老将刘薇调岗,前阿里高管加盟
- Machine learning notes - gray wolf optimization
- 想问下大家伙,有无是从腾讯云MYSQL同步到其他地方的呀?腾讯云MySQL存到COS上的binlog
- [recruitment position] Software Engineer (full stack) - public safety direction
- 危机重重下的企业发展,数字化转型到底是不是企业未来救星
- DVWA range clearance tutorial
猜你喜欢
两个BI开发,3000多张报表?如何做的到?
Interview shock 62: what are the precautions for group by?
爱可可AI前沿推介(7.5)
12 MySQL interview questions that you must chew through to enter Alibaba
超级哇塞的快排,你值得学会!
超越PaLM!北大碩士提出DiVeRSe,全面刷新NLP推理排行榜
No one consults when doing research and does not communicate with students. UNC assistant professor has a two-year history of teaching struggle
想进阿里必须啃透的12道MySQL面试题
Huawei Hubble incarnation hard technology IPO harvester
FR练习题目---综合题
随机推荐
超越PaLM!北大硕士提出DiVeRSe,全面刷新NLP推理排行榜
两个BI开发,3000多张报表?如何做的到?
Want to ask the big guy, is there any synchronization from Tencent cloud Mysql to other places? Binlog saved by Tencent cloud MySQL on cos
729. 我的日程安排表 I :「模拟」&「线段树(动态开点)」&「分块 + 位运算(分桶)」
FR练习题目---简单题
MySQL----函数
危机重重下的企业发展,数字化转型到底是不是企业未来救星
Au - delà du PARM! La maîtrise de l'Université de Pékin propose diverse pour actualiser complètement le classement du raisonnement du NLP
Handwriting promise and async await
Implement a blog system -- using template engine technology
[C question set] of Ⅷ
PyTorch二分类时BCELoss,CrossEntropyLoss,Sigmoid等的选择和使用
P1451 calculate the number of cells / 1329: [example 8.2] cells
ICML 2022 | 探索语言模型的最佳架构和训练方法
CPU design related notes
Ecotone technology has passed ISO27001 and iso21434 safety management system certification
CODING DevSecOps 助力金融企业跑出数字加速度
CODING DevSecOps 助力金融企业跑出数字加速度
Change multiple file names with one click
CPU设计实战-第四章实践任务三用前递技术解决相关引发的冲突