当前位置:网站首页>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
边栏推荐
- 想问下大家伙,有无是从腾讯云MYSQL同步到其他地方的呀?腾讯云MySQL存到COS上的binlog
- Coding devsecops helps financial enterprises run out of digital acceleration
- 危机重重下的企业发展,数字化转型到底是不是企业未来救星
- B站做短视频,学抖音死,学YouTube生?
- Cartoon: programmers don't repair computers!
- Stm32+bh1750 photosensitive sensor obtains light intensity
- 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 :「模拟」&「线段树(动态开点)」&「分块 + 位运算(分桶)」
- 漫画:优秀的程序员具备哪些属性?
- MySQL----函数
猜你喜欢

How can I quickly check whether there is an error after FreeSurfer runs Recon all—— Core command tail redirection

Your childhood happiness was contracted by it

Microframe technology won the "cloud tripod Award" at the global Cloud Computing Conference!
![[JVM] operation instruction](/img/f5/85580495474ef58eafbb421338e93f.png)
[JVM] operation instruction

Machine learning notes - gray wolf optimization

Surpass palm! Peking University Master proposed diverse to comprehensively refresh the NLP reasoning ranking

B站做短视频,学抖音死,学YouTube生?

No one consults when doing research and does not communicate with students. UNC assistant professor has a two-year history of teaching struggle

【NVMe2.0b 14-9】NVMe SR-IOV

黑马程序员-软件测试-10阶段2-linux和数据库-44-57为什么学习数据库,数据库分类关系型数据库的说明Navicat操作数据的说明,Navicat操作数据库连接说明,Navicat的基本使用,
随机推荐
easyOCR 字符识别
Detailed explanation of usememo, memo, useref and other relevant hooks
[detailed explanation of Huawei machine test] happy weekend
Drive brushless DC motor based on Ti drv10970
CODING DevSecOps 助力金融企业跑出数字加速度
Handwriting promise and async await
CPU设计相关笔记
手写promise与async await
DVWA range clearance tutorial
JS bright blind your eyes date selector
Magic methods and usage in PHP (PHP interview theory questions)
Fr exercise topic --- comprehensive question
B站做短视频,学抖音死,学YouTube生?
Your childhood happiness was contracted by it
729. 我的日程安排表 I :「模拟」&「线段树(动态开点)」&「分块 + 位运算(分桶)」
Crud of MySQL
两个BI开发,3000多张报表?如何做的到?
社区团购撤城“后遗症”
CPU设计实战-第四章实践任务三用前递技术解决相关引发的冲突
Super wow fast row, you are worth learning!