Redis实现漫衍式锁的正确要领

这里主要记录项目中利用基于Redis的漫衍式锁所碰着的问题及办理方案;

业务场景

我的业务场景是这样的,我们处事有库存模块,而我的处事又是多节点陈设,要岑岭期会存在库存差别,后头阐明问题之后,规划回收redis实现漫衍式锁(主要的原因是处事已经集成了redis,不需要做特另外设置)

踩坑1. 数据库事务超时

不要感受奇怪,漫衍式锁怎么会导致数据库事务超时呢?
我的代码或许是这样的:

伪代码 @Transaction(readOnly=false) void update(){ do{ redis=JedisUtil.getJedis(); flag = getLock(key,redis); if(flag){ update(); } }while(true) }

当你的key长时间获取不到锁,而且数据库事务都有超时时间的限制,那么就会呈现数据库事务超时问题;
办理方案

数据库事务改为手动提交事务;

踩坑2. redis key逾期,而业务没有执行完

我的key的逾期时间配置的是30s,假如30秒业务还没有执行完毕,锁就会自动释放,锁释放之后,其它线程又会去占用锁,同样会导致问题的产生;
办理方案

最简朴的办理方案就是利用redisson;
假如非要用redis来办理的话,只能利用按时器去检测key,假如说key尚有2秒就快逾期了,那么再为key从头配置30秒的逾期时间;

踩坑3. redis毗连池爆满

漫衍式锁刚加上之后,出产呈现一个问题,就是:redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
办理步伐
开始查代码,发明是开拓人员没有对毗连举办释放;

修复bug之后,又在线上跑了一段时间,又呈现了redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
办理步伐

void update(){ do{ redis=JedisUtil.getJedis(); flag = getLock(key,redis); if(flag){ update(); }else{ // 释放当前redis毗连 // 由于我们的业务场景属于较量耗时的业务型,所以在这里休眠1000毫秒 redis.close(); sleep(1000); } }while(true) }

1.当前请求获取锁,假如获取不到,则释放当前毗连,并休眠一会;
2.公道设置redis毗连池巨细,主要参考详细业务场景的并发量来配置;

踩坑4. 解铃还须系铃人

回首一下加锁的参数:

set(key, vlue,"NX","PX", 30000);

个中:value,我利用它来暗示加锁人,必需是一个独一的标识

好比:
A线程 key=test value=01
B线程 key=test value=02

假如A线程执行业务耗时高出了锁的持有时间,锁会自动释放;锁自动释放之后,线程B又加锁乐成,可是,此时A线程执行完业务逻辑之后,去释放锁,但A线程的锁已经自动释放了,假如没有value来标识的话,它大概就会去释放B线程的锁;

踩坑5. redis集群实现漫衍式锁

这种环境我没有碰着,因为公司的redis集群做了改造;

先说一下这种问题发生的原因:
假如master节点由于某原因产生了主从切换,那么就会呈现锁丢失的环境;

在master节点上拿到了锁;

可是这个加锁的key还没有同步到slave节点;

master妨碍,产生妨碍转移,slave节点进级为master节点;

故导致锁丢失;

办理步伐

需要通过利用redlock算法;
或利用redisson,它有对redlock算法做封装;

Linux公社的RSS地点https://www.linuxidc.com/rssFeed.aspx

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsdjjg.html