当前位置:网站首页>Record a failure caused by a custom redis distributed lock
Record a failure caused by a custom redis distributed lock
2022-07-26 01:20:00 【ImportNew】
( to ImportNew Plus star , Improve Java Skill )
background
redis setNX error java.lang.NumberFormatException: For input string: "null"at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)at java.lang.Long.parseLong(Long.java:589)at java.lang.Long.parseLong(Long.java:631)......
Locate by abnormal information , Discovery is customized in the project Redis Distributed lock error , And the exception occurred suddenly after the recent requirement was launched , And accompanied by the exception , There is also the problem of partial disorder of the business data involved in the requirements .
Problem analysis
Old rules , First post the code involved :
// sectionpublic class RedisLockAspect{public void around(ProceedingJoinPoint pjp) {String key = "...";try {// Blocking , Until the lock is acquiredwhile (!JedisUtil.lock(key, timeOut)) {Thread.sleep(10);}// Execute business logicpjp.proceed();}finally {JedisUtil.unLock(key);}}}
The above is customized Redis Facets of distributed locks , Don't look at the details , Just look at the overall logic , No big problem .
public class JedisUtil{public static boolean lock(String key, long timeOut){long currentTimeMillis = System.currentTimeMillis();long newExpireTime = currentTimeMillis + timeOut;RedisConnection connection = null;try {connection = getRedisTemplate().getConnectionFactory().getConnection();Boolean setNxResult = connection.setNX(key.getBytes(StandardCharsets.UTF_8), String.valueOf(newExpireTime).getBytes(StandardCharsets.UTF_8));// Location 1if(setNxResult){expire(key,timeOut, TimeUnit.MILLISECONDS);return true;}// Location 2Object objVal = getRedisTemplate().opsForValue().get(key);String currentValue = String.valueOf(objVal);// Location 3, The abnormal position is if In judgment Long.parseLong(currentValue),currentValue by null Stringif (currentValue != null && Long.parseLong(currentValue) < currentTimeMillis) {String oldExpireTime = (String) getAndSet(key, String.valueOf(newExpireTime));if (oldExpireTime != null && oldExpireTime.equals(currentValue)) {return true;}}}return false;}public static void unLock(String key){getRedisTemplate().delete(key);}}
Experienced boss sees this code , I guess I can't help being rude , But let's leave it alone , Look at the wrong position first .
Abnormal information can be seen ,currentValue The value of is string “null”, namely String.valueOf(objVal) Medium objVal The object is null, That is to say Redis in ,key Corresponding value non-existent .
Now think about it ,key Corresponding value non-existent , There are only two cases :
key Be actively deleted
key Out of date
Continue to follow the code up , It is found that setNx command , And back to setNxResult Indicates whether it was successful .
Normally , When setNxResult by false When , Locking failed , At this point, the code should not go down , But in this code , But continue to go down !
Asked relevant colleagues , It is said that it is to make a reentrant lock ......( Weak roast , But the re-entry lock doesn't work like this ...)
In fact, this analysis , You can already know what caused the abnormal fault , That's what it says ,key Be actively deleted 、key Due to expiration .
Let's assume that there are two threads , To the same key Lock , Corresponding to the above two situations respectively :
①key Being deleted voluntarily , Occurs after the distributed locking logic is executed , call unlock Method , See above RedisLockAspect Class finally part , Here's the picture :


Solution
From the code above , It's not simple anymore Long.parseLong("null") Problem. , This is the whole thing Redis The problem of distributed lock implementation .
And the distributed lock is widely used in the whole project , It is conceivable that the problem is very serious , If it's just a solution Long.parseLong("null") The problem of , There is no doubt that it is tickling between boots , It doesn't make any sense .
In general , Customize Redis Distributed locks are prone to the following problems :
setNx Lock release problem
setNx Expire Atomic question
Lock expiration problem
Multi thread lock release problem
Reentrant problem
Spinlock problem in case of a large number of failures
Lock data synchronization under master-slave architecture
Combined with the above fault codes , You can find Redis The implementation of distributed locks is hardly correct Redis Consider the distributed lock problem .
The following are the main problems and corresponding solutions :
setNx and expire Atomic manipulation : Use Lua Script , In a Lua In the script command , perform setNx And expire command , Guaranteed atomicity .
Lock expiration problem : To prevent the lock from automatically expiring , Before the lock expires , Periodically renew the lock expiration time .
Reentrant problem : The granularity of reentrant design needs to reach the thread level , Thread uniqueness can be added to the lock id.
Lock spin problem : Reference resources JDK in AQS Design , To achieve the maximum waiting time when acquiring a lock .
For the problems in the project and the solution implementation of each problem ,baidu There are a lot of references at once , No more about .
public class RedisLockAspect{@Autowiredprivate Redisson redisson;public void around(ProceedingJoinPoint pjp) {String key = "...";Long waitTime = 3000L;// Get the lockRLock lock = redisson.getLock(key);boolean lockSuccess = false;try {// Lock and set timeout , Prevent infinite spin . The watchdog function is enabled by default ( Automatically renew locks )lockSuccess = lock.tryLock(waitTime);// Execute business logicpjp.proceed();}finally {// Unlock , Prevent other thread locks from being releasedif (lock.isLocked() && lock.isHeldByCurrentThread() && lockSuccess){lock.unlock();}}}}
Use Redisson It can quickly solve the problems in the current project Redis Problems with distributed locks . besides , about Redis Lock problem caused by data synchronization in master-slave architecture , Corresponding solutions RedLock, The corresponding implementation is also provided .
summary
For distributed locks , The realizable scheme is far more than Redis This implementation approach , For example, based on Zookeeper、 be based on Etcd And so on .
But for the purpose , They all go the same way , The point is , How to safely 、 Use these solutions correctly , Make sure the business is normal .
For the R & D team , For similar problems , Technical partners need to be trained , Keep improving technology , We need to pay more attention to codereview Work , Identify risks in a timely manner , Avoid serious loss caused by failure ( This failure caused dirty data repair to take more than a week ).
Fear technology , Loyal to business .
from : Ten years of training experience
link :https://juejin.cn/post/7113852140455460900
- EOF -
Dig three feet Redis And MySQL Data consistency issues
It's solved Redis Big key problem , His colleagues praised him for bragging
Comfortable. , Step on an unusual about distributed locks BUG!
After reading this article, there are gains ? Please forward to share with more people
Focus on 「ImportNew」, promote Java Skill

Praise and watching is the greatest support ️
边栏推荐
- What are the ways to quickly improve programming skills in the process of programming learning?
- 全国一半人跑长沙,长沙一半人跑哪?
- # 浏览器开发使用技巧
- Diablo: immortality mobile game how to open more brick moving and novice introduction brick moving strategy
- NiO simple example
- Detailed explanation of at and crontab commands of RHCE and deployment of Chrony
- Arthas watch command to view the properties of objects in the array
- TV software burning
- Optimization of tableview
- 数据库系统原理与应用教程(053)—— MySQL 查询(十五):字符型函数的用法
猜你喜欢

网络文件传输之零拷贝

What is informatization? What is digitalization? What are the connections and differences between the two?

Detailed explanation of redis data structure, combined with books

Pycharm automatically adds header comments when creating py files

RHCE之at和crontab命令详解及chrony部署

IP地址能精确到哪步?动态IP及静态IP是什么?切换IP最常用的方法

FreeBSD bnxt以太网驱动源码阅读记录二:

2022年最新北京建筑八大员(材料员)模拟考试试题及答案

《分布式微服务电商》专题(一)-项目简介
![[CTF] crypto preliminary basic outline](/img/a9/bbaff7a23396dff4e486d5cd026b31.png)
[CTF] crypto preliminary basic outline
随机推荐
Prime Ring Problem
Sqli-labs Less7
iNFTnews | 假如这是元宇宙20年后的样子
Linked list related interview questions
Leetcode 537. 复数乘法(网友思路,自愧不如)
Web middleware log analysis script 3.0 (shell script)
如何获取广告服务流量变现数据,助力广告效果分析?
数据库系统原理与应用教程(053)—— MySQL 查询(十五):字符型函数的用法
换ip软件的用途很广及原理 动态IP更换的四种方法来保护网络隐私
Tutorial on principles and applications of database system (055) -- MySQL query (XVII): usage of mathematical functions
[CTF] crypto preliminary basic outline
[go] III. The simplest restful API server
数据库系统原理与应用教程(055)—— MySQL 查询(十七):数学函数的用法
U++学习笔记 UStruct、UEnum声明以及函数库简单函数实现
Docker advanced -mysql master-slave replication
Redis数据结构详解,结合书本
What are the ways to quickly improve programming skills in the process of programming learning?
[RTOS training camp] learn C language from a higher perspective
SQL的CASE WHEN
B - Krypton Factor(dfs+回溯法)