当前位置:网站首页>Redis distributed lock
Redis distributed lock
2022-07-01 16:47:00 【BugMaker-shen】
List of articles
One 、 Distributed lock concept
With the needs of business development , The system deployed by the original single machine is evolved into a distributed cluster system , Due to multithreading in distributed system 、 Multi process and distributed on different machines , This will invalidate the concurrent control lock policy in the case of the original stand-alone deployment , pure Java API It doesn't provide the ability of distributed locks . In order to solve this problem, we need a kind of cross JVM To control the access of shared resources , This is the problem of distributed lock !
To put it more popularly , After locking in the cluster , No matter which machine is currently operating , All machines will recognize and wait , Other operations can only be carried out after the lock is released , This is the distributed lock , It works in all clusters
The mainstream implementation of distributed lock :
- Implementation of distributed lock based on Database
- Cache based (Redis etc. )
- be based on Zookeeper
Every distributed lock solution has its own advantages and disadvantages , among redis The highest performance zookeeper Highest reliability
Two 、 Use setnx Implementation lock
set stu:1:info “OK” nx px 10000
EX second : Set the expiration time of the key to second second ,,SET key value EX second The effect is equivalent to SETEX key second value
PX millisecond : Set the expiration time of the key to millisecond millisecond ,SET key value PX millisecond The effect is equivalent to PSETEX key millisecond value
NX : Only if the bond doesn't exist , To set the key ,SET key value NX The effect is equivalent to SETNX key value
XX : Only if the bond already exists , To set the key

- Multiple clients acquire locks at the same time (setnx)
- To be successful , Execute business logic ( from db get data , Put into cache ), Execute complete release lock (del)
- The failed client will wait for retry

use setnx and del Add and release locks

In a general way , We need to set an expiration time for the lock to prevent it from being occupied for a long time

Here's the problem : Locking and setting expiration time are two operations , Instead of operating at the same time , If something abnormal happens after locking , You can't set the expiration time . We can Set the expiration time while locking

3、 ... and 、 Write code to test distributed locks
1. Use Java Code testing distributed locks
First, in the redis Set in num The value of is 0, To write Java Code to test
What the code below does is : Get the lock num++, And release the lock ; If you don't get it 0.1 Get it back in seconds 
restart , Service cluster , Pass the gateway stress test :ab -n 5000 -c 100 http://192.168.140.1:8080/test/testLock

see redis in num Value

problem : setnx Just got the lock , Exception in business logic , Causes the lock to fail to release
solve : Set expiration time , Automatic release lock
2. Optimize the lock expiration time
There are two ways to set the expiration time :
- The first thing to think about is through expire Set expiration time ( Lacking atomicity : If in setnx and expire And Exception occurred between , The lock doesn't release either )
- stay set Specify the expiration time at the same time ( recommend )

Set the expiration time in the code :

problem : May release locks on other servers
If the execution time of business logic is 7s, The execution process is as follows :
- index1 Business logic is not finished ,3 Seconds later, the lock is released automatically
- index2 Get lock , Execute business logic ,3 Seconds later, the lock is released automatically
- index3 Get lock , Execute business logic
- index1 Business logic execution complete , Start calling del Release the lock , What's released is index3 Lock of , Lead to index3 Our business only performs 1s I'll be released by someone else .
In the end, it's the case of no lock

a Stuck during operation , Cause the lock to automatically release after timeout ; After release ,b Grab the lock and operate ; here a Operation is completed , Release the lock manually , That's all. b My lock has been released ,b Releasing the lock again will report an error
solve : setnx When you get the lock , Set a specified unique value ( for example :uuid); Get this before release It's worth , Judge if it's your own lock
Four 、 Give optimization lock Set up UUID Error proofing


5、 ... and 、 Use LUA Scripts guarantee atomicity of deletion
Use lock Of uuid It can relieve the thread from releasing other locks to a certain extent , But this situation cannot be completely solved . Because it's more uuid And delete lock It's not atomic

problem : a Compare uuid After the adoption of , When the lock expires, it will be released automatically ,b Re lock ,a At this time, it will be released manually b Lock of , There is still a problem
solve : Use LUA Scripts guarantee atomicity of deletion
LUA Script :
Will be complex or multi-step redis operation , Write it as a script , Submit to redis perform , Reduce repeated connections redis The number of times , Lifting performance
LUA The script is similar to redis Business , It has certain atomicity , Will not be interrupted by other orders , You can do some redis transactional
@GetMapping("testLockLua")
public void testLockLua() {
//1 Make a statement uuid , Will be as a value Put in our key In the corresponding value
String uuid = UUID.randomUUID().toString();
//2 Define a lock :lua Scripts can use the same lock , To delete !
String skuId = "25"; // visit skuId by 25 No 100008348542
String locKey = "lock:" + skuId; // What's locked is the data of each commodity
// 3 Get the lock
Boolean lock = redisTemplate.opsForValue().setIfAbsent(locKey, uuid, 3, TimeUnit.SECONDS);
// The first one is : lock Don't write any code between the expiration time .
// redisTemplate.expire("lock",10, TimeUnit.SECONDS);// Set expiration time
// If true
if (lock) {
// The business logic of execution begins
// Get the num data
Object value = redisTemplate.opsForValue().get("num");
// If it's empty, return to
if (StringUtils.isEmpty(value)) {
return;
}
// Not empty If something goes wrong here ! that delete The deletion failed ! That is to say, the lock always exists !
int num = Integer.parseInt(value + "");
// send num Every time +1 Put into cache
redisTemplate.opsForValue().set("num", String.valueOf(++num));
/* Use lua Script to lock */
// Definition lua Script : Judge and delete at the same time
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
// Use redis perform lua perform
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(script);
// Set the return value type by Long
// Because when you delete judgment , Back to 0, Encapsulate it as a data type . If it's not encapsulated, it will return by default String type ,
// So return the string and 0 There will be mistakes .
redisScript.setResultType(Long.class);
// The first is the execution script Script , The second thing that needs to be judged key, The third is key The corresponding value .
redisTemplate.execute(redisScript, Arrays.asList(locKey), uuid);
} else {
// Other threads wait
try {
// sleep
Thread.sleep(1000);
// When I wake up , Calling method .
testLockLua();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


To ensure that distributed locks are available , We should at least ensure that the implementation of the lock meets the following four conditions at the same time :
- Mutual exclusivity ; At any moment , Only one client can hold the lock
- A deadlock will not occur ; Even if a client crashes while holding a lock without actively unlocking it , It can also ensure that other clients can be locked later ( Set up lock The expiration time of )
- He who breaks the bell must tie the bell ; Lock and unlock must be the same client , The client can't unlock the lock added by others ( Use LUA Scripts and uuid)
- Locking and unlocking must be atomic ( Use LUA Script )
边栏推荐
- Buuctf gold III
- Why is the pkg/errors tripartite library more recommended for go language error handling?
- Tutorial on principles and applications of database system (004) -- MySQL installation and configuration: resetting MySQL login password (Windows Environment)
- Tutorial on the principle and application of database system (002) -- MySQL installation and configuration: MySQL software uninstallation (Windows Environment)
- Tutorial on the principle and application of database system (001) -- MySQL installation and configuration: installation of MySQL software (Windows Environment)
- Go 语言怎么优化重复的 if err != nil 样板代码?
- Today, at 14:00, 15 ICLR speakers from Hong Kong University, Beihang, Yale, Tsinghua University, Canada, etc. continue!
- VMware 虚拟机启动时出现故障:VMware Workstation 与 Hyper-v 不兼容...
- 数据库系统原理与应用教程(002)—— MySQL 安装与配置:MySQL 软件的卸载(windows 环境)
- UML tourism management system "suggestions collection"
猜你喜欢

想做软件测试的女孩子看这里

How to solve the keyboard key failure of notebook computer

sql刷题627. 变更性别

Detailed explanation of activity life cycle and startup mode

Germany if was crowned with many awards. How strong is this pair of headphones? In depth evaluation of yinpo GTW 270 hybrid

游戏行业安全选择游戏盾,效果怎么样?

SQL question brushing 627 Change gender

C語言輸入/輸出流和文件操作
![[observation] where is the consulting going in the digital age? Thoughts and actions of softcom consulting](/img/82/3bb382893682a30e8af130365ec4ef.jpg)
[observation] where is the consulting going in the digital age? Thoughts and actions of softcom consulting
![[nodemon] app crashed - waiting for file changes before starting...解决方法](/img/ee/9830afd86e092851a2a906cb994949.png)
[nodemon] app crashed - waiting for file changes before starting...解决方法
随机推荐
Golang爬虫框架初探
博睿数据一体化智能可观测平台入选中国信通院2022年“云原生产品名录”
[jetsonnano] [tutorial] [introductory series] [III] build tensorflow environment
Installation and use of sqoop
Borui data integrated intelligent observable platform was selected into the "Yunyuan production catalogue" of China Academy of communications in 2022
【直播预约】数据库OBCP认证全面升级公开课
Chinese diosgenin market forecast and investment strategy report (2022 Edition)
为国产数据库添砖加瓦,StoneDB 一体化实时 HTAP 数据库正式开源!
sql刷题584. 寻找用户推荐人
判断一棵二叉树是否为平衡二叉树
sql刷题1050. 合作过至少三次的演员和导演
判断链表是否是回文链表
Hi Fun Summer, play SQL planner with starrocks!
Redis 分布式鎖
Sweden announced its decision to exclude Huawei 5g equipment, but Huawei has successfully found a new way out
阿里云、追一科技抢滩对话式AI
Template engine velocity Foundation
全面看待企业数字化转型的价值
Redis 分布式锁
接口测试框架中的鉴权处理