当前位置:网站首页>PHP uses redis to implement distributed locks
PHP uses redis to implement distributed locks
2022-07-06 06:19:00 【Miapenso】
Recently, when doing a coupon collection function , It is found that under certain concurrence, there will be the problem of repeated coupon collection . After a search operation with dueniang , It is found that distributed locks can be used to solve this problem .
What is distributed lock
Distributed lock is a way to control the synchronous access of shared resources between distributed systems . In distributed systems , It's often necessary to coordinate their movements . If different systems or different hosts of the same system share one or a group of resources , So when you visit these resources , We often need mutual exclusion to prevent interference with each other to ensure Uniformity , This is the time , You need to use distributed locks .
Realization principle
The principle of implementing distributed locks is very simple , Just need a lock , Multiple services acquire locks at the same time , But only one service can get the lock . The service that obtains the lock can execute its own business , Other services that have not obtained the lock need to wait for the lock to be released after the service business that has obtained the lock is completed , Then try to get the lock again .
There are many ways to realize distributed . as follows
- Implementation of distributed lock based on Database , such as mysql
- Implement distributed lock based on cache , such as redis
- be based on Zookeeper Implement distributed locks
Here we use redis To implement distributed locking , Get a before executing the business key, If key Existence means that other services have obtained locks , At this time, you need to wait or return to the busy system . If key non-existent , It indicates that no other service obtains the lock , Put this key Save to redis, And then execute the business , Wait until the business is completed, and then start from redis Delete this key.
php Implementation code
<?php
class RedisLock
{
protected $redis;
public function __construct(){
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$this->redis = $redis;
}
public function getLock($key){
$value = $this->redis->get($key);
return $value;
}
public function setLock($key,$value){
$this->redis->set($key,$value);
}
public function delLock($key){
$lineNumber = $thid->redis->del($key);
return $lineNumber;
}
}
$key = 'your_lock_key';
$value = time();
$redisLock = new RedisLock();
$isLock = $redisLock->get($key);
if($isLock) {
// Existing lock , Go straight back to , No more execution
return false;
}
// There is no lock , Lock
$redisLock->setLock($key,$value);
//todo Execute business logic
sleep(5);
// Unlock
$redisLock->delLock($key);
Use ab To test
Lock
Lock
Lock
Lock
Lock
Lock
Lock
Lock
Executive business
Unlock
Unlock
Executive business
Unlock
Executive business
Unlock
Executive business
Unlock
Unlock
Executive business
Unlock
Lock
Executive business
Unlock
Lock
Executive business
Unlock From the test results , It is found that there are multiple execution businesses , Not completely locked . This is because we use redis Of set command .set Command is used to set a given key Value . If key Other values have been stored , SET Just overwrite the old value , And ignore the type . This will cause many services to lock successfully , What we want is that only one service can lock successfully .
To solve this problem , Need to know redis Another order of setnx.setnx The order is at the designated key When there is no , by key Set the specified value .
<?php
class RedisLock
{
protected $redis;
public function __construct(){
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$this->redis = $redis;
}
public function getLock($key){
$value = $this->redis->get($key);
return $value;
}
public function setLock($key,$value){
return $this->redis->setnx($key,$value);
}
public function delLock($key){
$lineNumber = $thid->redis->del($key);
return $lineNumber;
}
}
$key = 'your_lock_key';
$value = time();
$redisLock = new RedisLock();
$isLock = $redisLock->get($key);
if($isLock) {
// Existing lock , Go straight back to , No more execution
return false;
}
// There is no lock , Lock
$setLock = $redisLock->setLock($key,$value);
if(!$setLock) {
// Locking failed
return false;
}
//todo Execute business logic
sleep(5);
// Unlock
$redisLock->delLock($key);
Again using ab To test
Lock
Lock
Lock
Lock
Lock
Lock
Lock
Locking failed
Locking failed
Locking failed
Locking failed
Locking failed
Locked
Locked
Locked
Executive business
Unlock From the test results , In the unlocked state , Multiple services acquire locks at the same time , But only one lock succeeded , All the others return locking failure , The following services directly return locked . thus it can be seen , Locking success .
So is that the end ? It's not . If the business is carried out in a locked situation , In the business process, an exception occurs for some reasons, resulting in the exit without unlocking , Then it will cause deadlock , All the following services cannot acquire the lock again . To solve this problem , We need to set an expiration time for the lock , Prevent deadlock .
<?php
class RedisLock
{
protected $redis;
public function __construct(){
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$this->redis = $redis;
}
public function getLock($key){
$value = $this->redis->get($key);
return $value;
}
public function setLock($key,$value,$second){
$setnx = $this->redis->setnx($key,$value);
if(!$setnx) {
return $setnx;
}
$expire = $this->redis->expire($key,$second);
if(!$expire) {
$this->redis->del($key);
}
return $expire;
}
public function delLock($key){
$lineNumber = $thid->redis->del($key);
return $lineNumber;
}
}
$key = 'your_lock_key';
$value = time();
$redisLock = new RedisLock();
$isLock = $redisLock->get($key);
if($isLock) {
// Existing lock , Go straight back to , No more execution
return false;
}
// There is no lock , Lock
$second = 5;
$setLock = $redisLock->setLock($key,$value,$second);
if(!$setLock) {
// Locking failed
return false;
}
//todo Execute business logic
sleep(5);
// Unlock
$redisLock->delLock($key);
So is this the end ? Welcome to tell me in the comment area ~
边栏推荐
- Coordinatorlayout+nestedscrollview+recyclerview pull up the bottom display is incomplete
- 黑猫带你学eMMC协议第10篇:eMMC读写操作详解(read & write)
- [C language] string left rotation
- Web界面元素的测试
- 技术分享 | 常见接口协议解析
- Amazon Engineer: eight important experiences I learned in my career
- Significance of unit testing
- Resttemplate and feign realize token transmission
- Linux regularly backs up MySQL database
- isam2运行流程
猜你喜欢
随机推荐
模拟卷Leetcode【普通】1405. 最长快乐字符串
Summary of anomaly detection methods
JDBC Requset 对应内容及功能介绍
Simulation volume leetcode [general] 1218 Longest definite difference subsequence
职场进阶指南:大厂人必看书籍推荐
模拟卷Leetcode【普通】1296. 划分数组为连续数字的集合
G - Supermarket
数据库-当前读与快照读
[eolink] PC client installation
Significance of unit testing
JMeter做接口测试,如何提取登录Cookie
G - Supermarket
selenium源码通读·9 |DesiredCapabilities类分析
leetcode 24. 两两交换链表中的节点
自定义指定路由上的Gateway过滤器工厂
The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
Hypothesis testing learning notes
[wechat applet] build a development tool environment
【Postman】测试(Tests)脚本编写和断言详解
F - True Liars (种类并查集+DP)
![[API interface tool] Introduction to postman interface](/img/03/c1541fca65dd726fd4bdc8793b605e.png)





![[postman] test script writing and assertion details](/img/65/6520fe78bb2b3ff99f16d09ea8c0d1.png)
