当前位置:网站首页>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
边栏推荐
- 在Pytorch中使用Tensorboard可视化训练过程
- Differences between IPv6 and IPv4 three departments including the office of network information technology promote IPv6 scale deployment
- 729. My schedule I: "simulation" & "line segment tree (dynamic open point) &" block + bit operation (bucket Division) "
- [detailed explanation of Huawei machine test] happy weekend
- Magic methods and usage in PHP (PHP interview theory questions)
- Stop B makes short videos, learns Tiktok to die, learns YouTube to live?
- Does maxcompute have SQL that can query the current storage capacity (KB) of the table?
- P6183 [USACO10MAR] The Rock Game S
- CPU design practice - Chapter 4 practice task 3 use pre delivery technology to solve conflicts caused by related issues
- 1330: [example 8.3] minimum steps
猜你喜欢
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
Mongdb learning notes
做研究无人咨询、与学生不交心,UNC助理教授两年教职挣扎史
[12 classic written questions of array and advanced pointer] these questions meet all your illusions about array and pointer, come on!
Talking about how dataset and dataloader call when loading data__ getitem__ () function
市值蒸发超百亿美元,“全球IoT云平台第一股”赴港求生
Implement a blog system -- using template engine technology
Your childhood happiness was contracted by it
想进阿里必须啃透的12道MySQL面试题
【jvm】运算指令
随机推荐
webRTC SDP mslabel lable
[detailed explanation of Huawei machine test] character statistics and rearrangement
【招聘岗位】基础设施软件开发人员
Under the crisis of enterprise development, is digital transformation the future savior of enterprises
美团优选管理层变动:老将刘薇调岗,前阿里高管加盟
useMemo,memo,useRef等相关hooks详解
Jmeter性能测试:ServerAgent资源监控
I collect multiple Oracle tables at the same time. After collecting for a while, I will report that Oracle's OGA memory is exceeded. Have you encountered it?
Drive brushless DC motor based on Ti drv10970
Mongdb learning notes
Selection and use of bceloss, crossentropyloss, sigmoid, etc. in pytorch classification
PyTorch二分类时BCELoss,CrossEntropyLoss,Sigmoid等的选择和使用
安装配置Jenkins
Type declaration of all DOM elements in TS
MySQL之CRUD
Implement a blog system -- using template engine technology
[12 classic written questions of array and advanced pointer] these questions meet all your illusions about array and pointer, come on!
选择排序和冒泡排序
浅谈Dataset和Dataloader在加载数据时如何调用到__getitem__()函数
百亿按摩仪蓝海,难出巨头