当前位置:网站首页>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 )
边栏推荐
- 程序员职业生涯真的很短吗?
- 剑指 Offer II 015. 字符串中的所有变位词
- 制造业数字化转型究竟是什么
- How to repair the laptop that cannot connect to the wireless network
- Leetcode 77 combination -- backtracking method
- Redis 分布式鎖
- Bugku's file contains
- Origin2018安装与使用(整理中)
- Virtual serial port simulator and serial port debugging assistant tutorial "suggestions collection"
- 独家消息:阿里云悄然推出RPA云电脑,已与多家RPA厂商开放合作
猜你喜欢
How to solve the keyboard key failure of notebook computer
Tutorial on the principle and application of database system (001) -- MySQL installation and configuration: installation of MySQL software (Windows Environment)
Défaillance lors du démarrage de la machine virtuelle VMware: le poste de travail VMware n'est pas compatible avec hyper - V...
Is the programmer's career really short?
[observation] where is the consulting going in the digital age? Thoughts and actions of softcom consulting
sql刷题1050. 合作过至少三次的演员和导演
数据库系统原理与应用教程(003)—— MySQL 安装与配置:手工配置 MySQL(windows 环境)
Buuctf gold III
Alibaba cloud, Zhuoyi technology beach grabbing dialogue AI
为国产数据库添砖加瓦,StoneDB 一体化实时 HTAP 数据库正式开源!
随机推荐
模板引擎Velocity 基礎
Introduction to software engineering - Chapter 6 - detailed design
Activity的生命周期和启动模式详解
Go 语言源码级调试器 Delve
Exclusive news: Alibaba cloud quietly launched RPA cloud computer and has opened cooperation with many RPA manufacturers
vim用户自动命令示例
【Kotlin】高阶函数介绍
制造业数字化转型究竟是什么
AI college entrance examination volunteer filling: the gods of Dachang fight, and candidates pay to watch
【直播预约】数据库OBCP认证全面升级公开课
Stegano in the world of attack and defense
How to solve the keyboard key failure of notebook computer
Leetcode 77 combination -- backtracking method
How to restore the system with one click on Lenovo laptop
What are the differences between PHP and DW
Is the securities account given by the head teacher of goucai school safe? Can I open an account?
全面看待企业数字化转型的价值
SQL question brushing 584 Looking for user references
Research and investment strategy report of neutral protease industry in China (2022 Edition)
阿里云、追一科技抢滩对话式AI