redis会发生死锁问题吗

redis会发生死锁问题吗

分布式锁而言,一个常用的问题就是如果一个服务setnx成功了,但是在解锁的时候如果发生了宕机或者一些特殊因素,导致无法解锁,那么其他服务将陷入死锁的状态。所以,我们在用 setnx 的同时想着去用 expire 指令对锁进行一个过期操作, 从指令可以看出 setnx 和expire指令是分开的,如果在这中间的空隙过程中如果有特殊因素导致指令无法继续,也会导致死锁的产生。

解决方法:

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils;   @Component public class RedisLock {       Logger logger = LoggerFactory.getLogger(this.getClass());       @Autowired     private StringRedisTemplate redisTemplate;       /**      * 加锁      * @param key         * @param value 当前时间 + 超时时间      * @return      */     public boolean lock(String key, String value) {              if (redisTemplate.opsForValue().setIfAbsent(key, value)) {                  // 这个其实就是setnx命令,只不过在java这边稍有变化,返回的是boolean             // 设置个过期时间,当然如果在这中间的空隙过程中如果有特殊因素导致指令无法继续,也会导致死锁的产生,如果死锁出现,则后续代码会处理             redisTemplate.expire(key, lockTime, TimeUnit.SECONDS);             return true;         }           // 避免死锁,且只让一个线程拿到锁         String currentValue = redisTemplate.opsForValue().get(key);         // 如果锁过期了         if (!StringUtils.isEmpty(currentValue) &amp;&amp; Long.parseLong(currentValue) <p>调用:<br></p><pre class="brush:php;toolbar:false"> //加锁     long time = System.currentTimeMillis() + 1000 * lockTime //超时时间:10秒,最好设为常量       boolean isLock = redisLock.lock(...keyName, String.valueOf(time));     if(!isLock){         throw new RuntimeException("系统正忙");     }          // doSomething...               //解锁     redisLock.unlock(...keyName, String.valueOf(time));

更多Redis相关知识,请访问Redis使用教程栏目!

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享