当前位置:网站首页>Redis distributed lock principle and its implementation with PHP (2)
Redis distributed lock principle and its implementation with PHP (2)
2022-07-05 15:05:00 【Back end regular developers】
List of articles
Lock in our daily development can be used more . Usually used to solve the problem of resource concurrency . Especially in the case of multi machine cluster , The problem of resource contention . however , Many novices often make some problems in dealing with locks . Today we 're going to take a deeper look at locks .
One 、Redis One of the lock misuses
I've seen projects that store query results in Redis The pseudo code is as follows :
$redis = new \Redis('127.0.0.1', 6379);
$cacheKey = 'query_cache';
$result = $redis->get($cacheKey);
if ($result) {
// If the cache is valid, it will directly return
return $result;
} else {
// If the cache fails, get it from the database and store it in the Redis
$mysqlResult = getDataFromDb();
$redis->set($cacheKey, json_encode($mysqlResult), 3600);
return $mysqlResult;
}
At first glance, the code doesn't find the problem . Usually , When the server resource pressure is very small , There's no problem with this code . also , It can really improve server throughput performance .
If , There is a single point of pressure on the code at this location ? such as , This function is statistical result , It takes 5s. and , Because this function is commonly used , Reached in unit time 1000 Time / second .
At this time, there will be concurrency penetration problem .
1000 Requests arrive at this program location at the same time , Read whether the cache exists . If the cache does not exist at this time . this 1000 Every request will get a result that doesn't exist . And they will all go to the steps of fetching the cached results from the database . It also rewrites the result to Redis.
That leads to a single point of pressure at this instant that leads to penetration into the database , Cause database pressure to peak in an instant . If the performance of our database can't handle such a big pressure , Will cause the database server to CPU Fill up directly . The data that responds to the front end will come to a standstill .
therefore , This code is incorrect lock usage .
Two 、Redis The second wrong use of lock
In the first point , We found a problem . therefore , Someone wants to optimize it . So here's the code :
$redis = new \Redis('127.0.0.1', 6379);
$lockKey = 'query_cache_lock'; // Lock specific KEY
$cacheKey = 'query_cache'; // Store query results KEY
$result = $redis->get($cacheKey);
if ($result) {
// If the cache is valid, it will directly return .
return $result;
} else {
// If the cache fails, get it from the database and store it in the Redis
if ($redis->setNx($lockKey) === false) {
throw new \Exception(" The server is hot , Please try again later ");
} else {
$mysqlResult = getDataFromDb();
$redis->set($cacheKey, json_encode($mysqlResult), 3600);
$redis->delete($lockKey); // Lock out to unlock . Delete is unlock .
return $mysqlResult;
}
}
This code completely avoids the problem of concurrency penetration in the first point . however , Relative to the first point , The code also added a few lines . But the performance is still strong .
Even so , There are still three problems with this code :
- The more concurrent , The first request to get the lock can respond normally , A subsequent request will get a “ The server is hot , Please try again later ” The exception of .
- There is no way to add a waiting time to the failure of subsequent request to take lock .
- If the code executes to r e d i s − > d e l e t e ( redis->delete( redis−>delete(lockKey) The program is abnormal . Then the lock will not release normally . Subsequent locks can't be taken normally .
For (1) spot , This is a very poor user experience .
For (2) spot , It's the solution to the first point .
For (3) spot , It's a problem we have to solve . otherwise , Our distributed locks will not work .
3、 ... and 、 Right distributed lock
The normal distributed lock should meet the following requirements :
- Can solve concurrent resource contention . This is the core requirement .
- Lock can be added and released normally . No deadlocks .
- Lock can realize waiting , Otherwise, the user experience cannot be guaranteed .
For the above three points , obtain Redis Distributed lock example
class RedisMutexLock {
/** * return Redis Connect * * @return void */
public static function getRedis() {
// Please replace this line of code with your own get according to your own project Redis Connect
return YCache::getRedisClient();
}
/** * Gets the lock , If the lock is occupied , Blocking , Until the lock is obtained or the timeout is reached * -- 1、 If $timeout Parameter is 0, Then immediately return to the lock * -- 2、 Suggest timeout Set to 0, avoid redis Performance degradation due to congestion. Please set it according to actual requirements * * @param string $key cache KEY * @param int $timeout Lock taking timeout unit ( second ) be equal to 0, If the current lock is occupied , Immediately return failure if greater than 0, Then repeatedly try to acquire the lock until the timeout is reached * @param int $lockSecond Lock time unit ( second ) * @param int $sleep Lock taking interval unit ( Microsecond ) When the lock is in the occupied state, how often do you try to get the lock by default 0.1 Take the lock every second * @return bool success :true、 Failure :false */
public static function lock($key, $timeout = 0, $lockSecond = 20, $sleep = 100000) {
if (strlen($key) === 0) {
// Project throw exception method
YCore::exception(500, ' cache KEY No settings ');
}
$start = self::getMicroTime();
$redis = self::getRedis();
do {
// [1] The lock KEY It is not important to set its value when it does not exist and set the expiration time to the value of the specified time lock. What is important is to use Redis Characteristics of
$acquired = $redis->set("Lock:{
$key}", 1, ['NX', 'EX' => $lockSecond]);
if ($acquired) {
break;
}
if ($timeout === 0) {
break;
}
usleep($sleep);
} while (!is_numeric($timeout) || (self::getMicroTime()) < ($start + ($timeout * 1000000)));
return $acquired ? true : false;
}
/** * Release the lock * * @param mixed $key Locked KEY * @return void */
public static function release($key) {
if (strlen($key) === 0) {
// Project throw exception method
YCore::exception(500, ' cache KEY No settings ');
}
$redis = self::getRedis();
$redis->del("Lock:{
$key}");
}
/** * Get the current microsecond * * @return bigint */
protected static function getMicroTime() {
return bcmul(microtime(true), 1000000);
}
}
from :https://www.phpernote.com/redis/1621.html
边栏推荐
- How to paste the contents copied by the computer into mobaxterm? How to copy and paste
- 【华为机试真题详解】欢乐的周末
- Using tensorboard to visualize the training process in pytoch
- 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
- Under the crisis of enterprise development, is digital transformation the future savior of enterprises
- How to solve the problem of garbled code when installing dependency through NPM or yarn
- 机器学习框架简述
- Isn't it right to put money into the external market? How can we ensure safety?
- js亮瞎你眼的日期选择器
- 美团优选管理层变动:老将刘薇调岗,前阿里高管加盟
猜你喜欢
【华为机试真题详解】字符统计及重排
Drive brushless DC motor based on Ti drv10970
CPU设计相关笔记
Ctfshow web entry explosion
Live broadcast preview | how to implement Devops with automatic tools (welfare at the end of the article)
Fr exercise topic - simple question
FR练习题目---综合题
Run faster with go: use golang to serve machine learning
CODING DevSecOps 助力金融企业跑出数字加速度
Install and configure Jenkins
随机推荐
TS所有dom元素的类型声明
【招聘岗位】基础设施软件开发人员
两个BI开发,3000多张报表?如何做的到?
Interview shock 62: what are the precautions for group by?
FR练习题目---简单题
爱可可AI前沿推介(7.5)
729. My schedule I: "simulation" & "line segment tree (dynamic open point) &" block + bit operation (bucket Division) "
[C question set] of Ⅷ
30岁汇源,要换新主人了
PHP high concurrency and large traffic solution (PHP interview theory question)
【NVMe2.0b 14-9】NVMe SR-IOV
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
黑马程序员-软件测试-10阶段2-linux和数据库-44-57为什么学习数据库,数据库分类关系型数据库的说明Navicat操作数据的说明,Navicat操作数据库连接说明,Navicat的基本使用,
想进阿里必须啃透的12道MySQL面试题
超级哇塞的快排,你值得学会!
【C 题集】of Ⅷ
Photoshop plug-in action related concepts actionlist actiondescriptor actionlist action execution load call delete PS plug-in development
Photoshop plug-in - action related concepts - actions in non loaded execution action files - PS plug-in development
做研究无人咨询、与学生不交心,UNC助理教授两年教职挣扎史
Ctfshow web entry explosion