当前位置:网站首页>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
边栏推荐
- Rendu stéréo
- Dragon City in Europe | National Geographic the most romantic and safe destination in the world
- Solve the problem that MySQL in phpstudy cannot be started and conflicts with locally installed MySQL
- The first warm-up -- implicit type conversion or other?
- pycharm 配置远程连接服务器开发环境
- Developing salary management system based on C language course paper + source code and executable EXE file
- Codeup longest palindrome substring
- R language builds a binary classification model based on H2O package: using H2O GLM constructs regularized logistic regression model and uses H2O AUC value of AUC calculation model
- How to improve work efficiency? Macintosh efficiency tool set
- The method of making videos of knowledge payment system support m3u8 format playback
猜你喜欢

What are the indicators, dimensions and models in Business Intelligence BI data warehouse?

5 minutes to quickly launch web applications and APIs (vercel)

Las point cloud create mesh

Core and semiconductor "RF eda/ filter design platform" shines ims2022

2021-08-22

Redis error reporting and common configurations

Huawei cloud recruits partners in the field of industrial intelligence to provide strong support + commercial realization

General trend wisdom to create inclined model and cut monomer

2021-04-14

The link added in the bottom menu cannot jump to the secondary page
随机推荐
Some shaders in AB package do not trigger the callback of ipreprocessshaders
[Li mu] how to read papers [intensive reading of papers]
Eureka service registration and discovery
2020-12-04
2020-12-20
The relationship between derivative and differential of function
2021-08-21
322. change exchange
Redis-分布式锁
5 minutes to quickly launch web applications and APIs (vercel)
Cryptography series: certificate format representation of PKI X.509
Help customers' digital transformation and build a new operation and maintenance system
Why do you perform performance tests before the software goes online? How to find a software performance testing organization
Is it bad for NFT that the market starts to cool down?
2020-12-04
【象棋人生】01 人生如棋
R language data preprocessing, converting type variables into factor variables, converting data sets into H2O format, and dividing data sets (training set, test set, verification set)
Uniapp applet mall develops thinkphp6 points mall, group purchase and seckill packaged app
AtCoder abc256全题解(区间合并模板、矩阵快速幂优化dp、线段树……)
redis 报错解决与常用配置