当前位置:网站首页>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
边栏推荐
- go学习 ------jwt的相关知识
- CPU设计实战-第四章实践任务三用前递技术解决相关引发的冲突
- Ctfshow web entry information collection
- Magic methods and usage in PHP (PHP interview theory questions)
- 安装配置Jenkins
- Garbage collection mechanism of PHP (theoretical questions of PHP interview)
- [detailed explanation of Huawei machine test] happy weekend
- 可转债打新在哪里操作开户是更安全可靠的呢
- IPv6与IPv4的区别 网信办等三部推进IPv6规模部署
- Run faster with go: use golang to serve machine learning
猜你喜欢

Selection and use of bceloss, crossentropyloss, sigmoid, etc. in pytorch classification

"Sequelae" of the withdrawal of community group purchase from the city

FR练习题目---综合题

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

一键更改多个文件名字

729. 我的日程安排表 I :「模拟」&「线段树(动态开点)」&「分块 + 位运算(分桶)」

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

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

爱可可AI前沿推介(7.5)
![1330: [example 8.3] minimum steps](/img/69/9cb13ac4f47979b498fa2254894ed1.gif)
1330: [example 8.3] minimum steps
随机推荐
Photoshop插件-动作相关概念-非加载执行动作文件中动作-PS插件开发
Crud of MySQL
Coding devsecops helps financial enterprises run out of digital acceleration
FR练习题目---综合题
CODING DevSecOps 助力金融企业跑出数字加速度
Fr exercise topic --- comprehensive question
【C 题集】of Ⅷ
MySQL之CRUD
Run faster with go: use golang to serve machine learning
Isn't it right to put money into the external market? How can we ensure safety?
CPU设计实战-第四章实践任务三用前递技术解决相关引发的冲突
B站做短视频,学抖音死,学YouTube生?
百亿按摩仪蓝海,难出巨头
【招聘岗位】软件工程师(全栈)- 公共安全方向
计算中间件 Apache Linkis参数解读
[detailed explanation of Huawei machine test] happy weekend
在Pytorch中使用Tensorboard可视化训练过程
12 MySQL interview questions that you must chew through to enter Alibaba
Behind the ultra clear image quality of NBA Live Broadcast: an in-depth interpretation of Alibaba cloud video cloud "narrowband HD 2.0" technology
[recruitment position] infrastructure software developer