当前位置:网站首页>Learn redis with you (11) -- redis distributed lock
Learn redis with you (11) -- redis distributed lock
2022-06-22 22:54:00 【Reviewing the old and learning the new Java】
Keep creating , Accelerate growth ! This is my participation 「 Nuggets day new plan · 6 Yuegengwen challenge 」 Of the 5 God , Click to see the event details
Preface
In monomer applications , If we do not lock the shared data , There will be data consistency issues , Our solution is usually to lock . In a distributed architecture , We will also encounter data sharing operation problems , here , We need distributed locks to solve the problem , Let's talk about using redis To implement distributed locking .
Use scenarios
- Inventory oversold such as 5 A notebook A see Ready to buy 3 individual B buy 2 individual C 4 individual One order 3+2+4 =9
- Prevent users from placing repeated orders
- MQ The news is heavy
- Order operation change
Why use distributed locks
Analyze from the business scenario , There's one thing in common , Competition for shared resources , For example, stock goods , user , news , Orders, etc , These resources can only be operated by one thread at the same time , And during operation , Prohibit other thread operations . To achieve this effect , It is necessary to realize mutual exclusion of shared resources , Shared resource serialization . Actually , This is the problem of locking shared resources . In single application ( Single process multithreading ) Using locks in , We can use synchronize、ReentrantLock Other key words , Lock shared resources . In distributed applications ( Multiprocess and multithreading ) in , Distributed lock is a way to control the synchronous access of shared resources between distributed systems .
How to use distributed locks
flow chart
Status of distributed locks
- The client can only operate on the shared resources by competing for the lock
- When the client holding the lock operates on the shared resource
- No other client can operate on this resource
- Until the client holding the lock completes the operation
Features of distributed locks
- Mutual exclusivity
At any moment , Only one client can hold the lock ( exclusive )
- High availability , Fault tolerance
As long as most nodes in the lock service cluster are running normally , You can unlock the client
- Avoid deadlock
Lock failure mechanism , The lock must be released after a period of time .( Normal release or timeout release )
- Locking and unlocking are the same client
One client cannot release the lock added by other clients
The implementation of distributed locks ( With redis Take distributed lock implementation as an example )
Simple version
/** * Simple version * @author:liyajie * @createTime:2022/6/22 15:42 * @version:1.0 */
public class SimplyRedisLock {
// Redis Distributed locked key
public static final String REDIS_LOCK = "redis_lock";
@Autowired
StringRedisTemplate template;
public String index(){
// Everyone needs to lock before they come in ,key The value is "redis_lock",value Random generation
String value = UUID.randomUUID().toString().replace("-","");
try{
// Lock
Boolean flag = template.opsForValue().setIfAbsent(REDIS_LOCK, value);
// Locking failed
if(!flag){
return " Lock snatch failed !";
}
System.out.println( value+ " Successful lock snatching ");
// Business logic
String result = template.opsForValue().get("001");
int total = result == null ? 0 : Integer.parseInt(result);
if (total > 0) {
int realTotal = total - 1;
template.opsForValue().set("001", String.valueOf(realTotal));
// If after grabbing the place , Before deleting a lock , Something is wrong , The lock cannot be released ,
// The lock release operation cannot be performed here , To be in finally Handle
// template.delete(REDIS_LOCK);
System.out.println(" Successful purchase of goods , Stock left :" + realTotal + " Pieces of ");
return " Successful purchase of goods , Stock left :" + realTotal + " Pieces of ";
} else {
System.out.println(" Failed to buy goods ");
}
return " Failed to buy goods ";
}finally {
// Release the lock
template.delete(REDIS_LOCK);
}
}
}
The implementation scheme is relatively simple , But there are some problems . If the service hangs up while it is running , The code completes the locking process , But there's no use walking finally part , That is, the lock is not released , In this case , The lock can never be released . So there was an improved version .
Advanced version
/** * Advanced version * @author:liyajie * @createTime:2022/6/22 15:42 * @version:1.0 */
public class SimplyRedisLock2 {
// Redis Distributed locked key
public static final String REDIS_LOCK = "redis_lock";
@Autowired
StringRedisTemplate template;
public String index(){
// Everyone needs to lock before they come in ,key The value is "redis_lock",value Random generation
String value = UUID.randomUUID().toString().replace("-","");
try{
// Lock
Boolean flag = template.opsForValue().setIfAbsent(REDIS_LOCK, value,10L, TimeUnit.SECONDS);
// Locking failed
if(!flag){
return " Lock snatch failed !";
}
System.out.println( value+ " Successful lock snatching ");
// Business logic
String result = template.opsForValue().get("001");
int total = result == null ? 0 : Integer.parseInt(result);
if (total > 0) {
int realTotal = total - 1;
template.opsForValue().set("001", String.valueOf(realTotal));
// If after grabbing the place , Before deleting a lock , Something is wrong , The lock cannot be released ,
// The lock release operation cannot be performed here , To be in finally Handle
// template.delete(REDIS_LOCK);
System.out.println(" Successful purchase of goods , Stock left :" + realTotal + " Pieces of ");
return " Successful purchase of goods , Stock left :" + realTotal + " Pieces of ";
} else {
System.out.println(" Failed to buy goods ");
}
return " Failed to buy goods ";
}finally {
// Release the lock
template.delete(REDIS_LOCK);
}
}
}
This implementation , Yes key Added an expiration time , In this way, even if the service fails , After the expiration time , The lock will release automatically . But think about it , There is still a problem . such as key The expiration time of the value is 10s, But the business processing logic needs 15s Time for , This will cause a thread to process the business logic , Releasing the lock , Delete immediately key When , Delete the key Not myself set Of , It is set by other threads , This will cause data inconsistency , Errors that cause data , And affect the business . It needs to be improved .
Advanced version 2- Who set the lock , Who released
/** * Advanced version 2- Who set the lock , Who released * @author:liyajie * @createTime:2022/6/22 15:42 * @version:1.0 */
public class SimplyRedisLock3 {
// Redis Distributed locked key
public static final String REDIS_LOCK = "redis_lock";
@Autowired
StringRedisTemplate template;
public String index(){
// Everyone needs to lock before they come in ,key The value is "redis_lock",value Random generation
String value = UUID.randomUUID().toString().replace("-","");
try{
// Lock
Boolean flag = template.opsForValue().setIfAbsent(REDIS_LOCK, value,10L, TimeUnit.SECONDS);
// Locking failed
if(!flag){
return " Lock snatch failed !";
}
System.out.println( value+ " Successful lock snatching ");
// Business logic
String result = template.opsForValue().get("001");
int total = result == null ? 0 : Integer.parseInt(result);
if (total > 0) {
int realTotal = total - 1;
template.opsForValue().set("001", String.valueOf(realTotal));
// If after grabbing the place , Before deleting a lock , Something is wrong , The lock cannot be released ,
// The lock release operation cannot be performed here , To be in finally Handle
// template.delete(REDIS_LOCK);
System.out.println(" Successful purchase of goods , Stock left :" + realTotal + " Pieces of ");
return " Successful purchase of goods , Stock left :" + realTotal + " Pieces of ";
} else {
System.out.println(" Failed to buy goods ");
}
return " Failed to buy goods ";
}finally {
// Who added the lock , Who can delete !!!!
if(template.opsForValue().get(REDIS_LOCK).equals(value)){
template.delete(REDIS_LOCK);
}
}
}
}
This method solves the problem of complex business , Processing time is too long , Past due date , And the problem of releasing other people's locks . Are there any other questions ? In fact, there are still some ,finally Block judgment and del The delete operation is not atomic , There will also be problems during concurrency , Concurrency is to ensure data consistency , Ensure data consistency , It is best to ensure that the operation of data is atomic . So we still need to improve .
Advanced version 3-Lua edition
/** * Advanced version -Lua edition * @author:liyajie * @createTime:2022/6/22 15:42 * @version:1.0 */
public class SimplyRedisLock3 {
// Redis Distributed locked key
public static final String REDIS_LOCK = "redis_lock";
@Autowired
StringRedisTemplate template;
public String index(){
// Everyone needs to lock before they come in ,key The value is "redis_lock",value Random generation
String value = UUID.randomUUID().toString().replace("-","");
try{
// Lock
Boolean flag = template.opsForValue().setIfAbsent(REDIS_LOCK, value,10L, TimeUnit.SECONDS);
// Locking failed
if(!flag){
return " Lock snatch failed !";
}
System.out.println( value+ " Successful lock snatching ");
// Business logic
String result = template.opsForValue().get("001");
int total = result == null ? 0 : Integer.parseInt(result);
if (total > 0) {
int realTotal = total - 1;
template.opsForValue().set("001", String.valueOf(realTotal));
// If after grabbing the place , Before deleting a lock , Something is wrong , The lock cannot be released ,
// The lock release operation cannot be performed here , To be in finally Handle
// template.delete(REDIS_LOCK);
System.out.println(" Successful purchase of goods , Stock left :" + realTotal + " Pieces of ");
return " Successful purchase of goods , Stock left :" + realTotal + " Pieces of ";
} else {
System.out.println(" Failed to buy goods ");
}
return " Failed to buy goods ";
}finally {
// Who added the lock , Who can delete , Use Lua Script , Delete the lock
Jedis jedis = null;
try{
jedis = RedisUtils.getJedis();
String script = "if redis.call('get',KEYS[1]) == ARGV[1] " +
"then " +
"return redis.call('del',KEYS[1]) " +
"else " +
" return 0 " +
"end";
Object eval = jedis.eval(script, Collections.singletonList(REDIS_LOCK), Collections.singletonList(value));
if("1".equals(eval.toString())){
System.out.println("-----del redis lock ok....");
}else{
System.out.println("-----del redis lock error ....");
}
}catch (Exception e){
}finally {
if(null != jedis){
jedis.close();
}
}
}
}
}
This way, , Specifies who has the lock , Who can delete , It also solves the problem that the deletion operation has no atomicity . But cache has not been considered yet , as well as Redis Cluster deployment , Lock loss due to asynchronous replication : The master node didn't have time to set Enter this data to the slave node , I hung up. . So we have to improve .
Ultimate evolution
/** * Ultimate evolution * @author:liyajie * @createTime:2022/6/22 15:42 * @version:1.0 */
public class SimplyRedisLock5 {
// Redis Distributed locked key
public static final String REDIS_LOCK = "redis_lock";
@Autowired
StringRedisTemplate template;
@Autowired
Redisson redisson;
public String index(){
RLock lock = redisson.getLock(REDIS_LOCK);
lock.lock();
// Everyone needs to lock before they come in ,key The value is "redis_lock"
String value = UUID.randomUUID().toString().replace("-","");
try {
String result = template.opsForValue().get("001");
int total = result == null ? 0 : Integer.parseInt(result);
if (total > 0) {
// If you need to call other microservices here , Longer processing time ...
int realTotal = total - 1;
template.opsForValue().set("001", String.valueOf(realTotal));
System.out.println(" Successful purchase of goods , Stock left :" + realTotal + " Pieces of ");
return " Successful purchase of goods , Stock left :" + realTotal + " Pieces of ";
} else {
System.out.println(" Failed to buy goods ");
}
return " Failed to buy goods ";
}finally {
if(lock.isLocked() && lock.isHeldByCurrentThread()){
lock.unlock();
}
}
}
}
This implementation , The bottom layer encapsulates multiple nodes redis Implementation of the distributed lock algorithm , Effectively prevent single point of failure , If you are interested, you can study it .
summary
The process of analyzing problems , It is also the process of solving problems , It can also exercise the way and angle of thinking when writing code . About redis That's all for the correlation analysis of distributed locks , You have new ideas , Welcome to exchange and analyze .
end
If you need to exchange and learn, you can pay attention to official account 【 Review the old and know the new java】, learn from each other , Progress together
边栏推荐
- MySQL multi table operation
- Reinforcement learning weekly (issue 50): saferl kit, gmi-drl, rp-sdrl & offline meta reinforcement learning
- 【ROS】ROSmsg cakin_ Make compilation error
- Solution to cache inconsistency
- Makefile:1860: recipe for target ‘cmake_ check_ build_ system‘ failed make: *** [cmake_check_build_syst
- 2020-12-04
- Practice brings true knowledge: the strongest seckill system architecture in the whole network is decrypted. Not all seckills are seckills!!
- Las point cloud data thinning in ArcGIS
- Mysql8 installation and environment configuration
- What are the methods of software stress testing and how to select a software stress testing organization?
猜你喜欢

The link added in the bottom menu cannot jump to the secondary page

《强化学习周刊》第50期:SafeRL-Kit、GMI-DRL、RP-SDRL & 离线元强化学习

2021-08-21

2021-03-06

General trend wisdom to create inclined model and cut monomer

redis 报错解决与常用配置

How to continuously improve performance| DX R & D mode

c语言---17 函数简介

2020-12-04
Task cache compilation caused by gradle build cache
随机推荐
Note: by the end of 2022, the printing entrance of Guangdong second-class cost engineer's admission card has been opened
Valid parentheses
使用HBuilder X编辑器安装终端窗口插件未响应的解决方案
2021-07-27
Why is yuancosmos so popular? Is the 10trillion yuan shouted by the market boasting or the truth?
[chess life] 01 life is like chess
Wechat applet batch submission for review
Makefile:1860: recipe for target ‘cmake_ check_ build_ system‘ failed make: *** [cmake_check_build_syst
The method of making videos of knowledge payment system support m3u8 format playback
≥ server2012r2 system, disable some planned tasks of the system
2021-04-14
Help customers' digital transformation and build a new operation and maintenance system
Fundamentals of shell programming (Part 7: branch statement -if)
pycharm 配置远程连接服务器开发环境
Pycharm configuring remote connection server development environment
2020-12-20
What if the SQL execution plan of the production system suddenly becomes worse?
Rapideye, spot satellite remote sensing image data
Developing salary management system based on C language course paper + source code and executable EXE file
LinkedList 源码解析