当前位置:网站首页>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
边栏推荐
- JS bright blind your eyes date selector
- Coding devsecops helps financial enterprises run out of digital acceleration
- FR练习题目---简单题
- 729. 我的日程安排表 I :「模拟」&「线段树(动态开点)」&「分块 + 位运算(分桶)」
- Crud de MySQL
- Two Bi development, more than 3000 reports? How to do it?
- 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
- 如何将电脑复制的内容粘贴进MobaXterm?如何复制粘贴
- 超越PaLM!北大硕士提出DiVeRSe,全面刷新NLP推理排行榜
- Dark horse programmer - software testing -10 stage 2-linux and database -44-57 why learn database, description of database classification relational database, description of Navicat operation data, de
猜你喜欢
B站做短视频,学抖音死,学YouTube生?
当代人的水焦虑:好水究竟在哪里?
[detailed explanation of Huawei machine test] character statistics and rearrangement
Super wow fast row, you are worth learning!
【NVMe2.0b 14-9】NVMe SR-IOV
做研究无人咨询、与学生不交心,UNC助理教授两年教职挣扎史
黑马程序员-软件测试-10阶段2-linux和数据库-44-57为什么学习数据库,数据库分类关系型数据库的说明Navicat操作数据的说明,Navicat操作数据库连接说明,Navicat的基本使用,
Fr exercise topic - simple question
Machine learning notes - gray wolf optimization
Surpass palm! Peking University Master proposed diverse to comprehensively refresh the NLP reasoning ranking
随机推荐
Magic methods and usage in PHP (PHP interview theory questions)
mapper.xml文件中的注释
CPU设计实战-第四章实践任务二用阻塞技术解决相关引发的冲突
爱可可AI前沿推介(7.5)
【jvm】运算指令
长列表优化虚拟滚动
一键更改多个文件名字
Super wow fast row, you are worth learning!
Live broadcast preview | how to implement Devops with automatic tools (welfare at the end of the article)
STM32+BH1750光敏传感器获取光照强度
超级哇塞的快排,你值得学会!
P6183 [USACO10MAR] The Rock Game S
CPU design related notes
社区团购撤城“后遗症”
【华为机试真题详解】字符统计及重排
Easyocr character recognition
Using tensorboard to visualize the training process in pytoch
"Sequelae" of the withdrawal of community group purchase from the city
1330: [example 8.3] minimum steps
GPS原始坐标转百度地图坐标(纯C代码)