当前位置:网站首页>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
边栏推荐
- GPS原始坐标转百度地图坐标(纯C代码)
- 社区团购撤城“后遗症”
- 729. 我的日程安排表 I :「模拟」&「线段树(动态开点)」&「分块 + 位运算(分桶)」
- DVWA range clearance tutorial
- Long list optimized virtual scrolling
- "Sequelae" of the withdrawal of community group purchase from the city
- Install and configure Jenkins
- 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
- Fr exercise topic - simple question
- IPv6与IPv4的区别 网信办等三部推进IPv6规模部署
猜你喜欢

Live broadcast preview | how to implement Devops with automatic tools (welfare at the end of the article)

12 MySQL interview questions that you must chew through to enter Alibaba
![[JVM] operation instruction](/img/f5/85580495474ef58eafbb421338e93f.png)
[JVM] operation instruction
![1330: [example 8.3] minimum steps](/img/69/9cb13ac4f47979b498fa2254894ed1.gif)
1330: [example 8.3] minimum steps

CODING DevSecOps 助力金融企业跑出数字加速度

P1451 求细胞数量/1329:【例8.2】细胞

NBA赛事直播超清画质背后:阿里云视频云「窄带高清2.0」技术深度解读

选择排序和冒泡排序

危机重重下的企业发展,数字化转型到底是不是企业未来救星

Implement a blog system -- using template engine technology
随机推荐
机器学习框架简述
Ctfshow web entry explosion
【C 题集】of Ⅷ
Under the crisis of enterprise development, is digital transformation the future savior of enterprises
P1451 求细胞数量/1329:【例8.2】细胞
Stop B makes short videos, learns Tiktok to die, learns YouTube to live?
JMeter performance test: serveragent resource monitoring
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
The difference between abstract classes and interfaces in PHP (PHP interview theory question)
maxcompute有没有能查询 表当前存储容量的大小(kb) 的sql?
Fr exercise topic - simple question
机器学习笔记 - 灰狼优化
我这边同时采集多个oracle表,采集一会以后,会报oracle的oga内存超出,大家有没有遇到的?
Coding devsecops helps financial enterprises run out of digital acceleration
市值蒸发超百亿美元,“全球IoT云平台第一股”赴港求生
STM32+BH1750光敏传感器获取光照强度
Talk about your understanding of microservices (PHP interview theory question)
Interpretation of Apache linkage parameters in computing middleware
GPS original coordinates to Baidu map coordinates (pure C code)
729. 我的日程安排表 I :「模拟」&「线段树(动态开点)」&「分块 + 位运算(分桶)」