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) && Long.parseLong(currentValue) < System.currentTimeMillis()) { //获取上一个锁的时间 String oldValues = redisTemplate.opsForValue().getAndSet(key, value); /* 只会让一个线程拿到锁 如果旧的value和currentValue相等,只会有一个线程达成条件,因为第二个线程拿到的oldValue已经和currentValue不一样了 */ if (!StringUtils.isEmpty(oldValues) && oldValues.equals(currentValue)) { return true; } } return false; } /** * 解锁 * @param key * @param value */ public void unlock(String key, String value) { try { String currentValue = redisTemplate.opsForValue().get(key); if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) { redisTemplate.opsForValue().getOperations().delete(key); } } catch (Exception e) { logger.error("redis分布式锁解锁异常,{}", e); } } }
调用:
//加锁 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使用教程栏目!
以上是redis会发生死锁问题吗的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

本文讨论了在Redis群集中选择碎片键,并强调了它们对性能,可伸缩性和数据分布的影响。关键问题包括确保均匀数据分配,与访问模式保持一致以及避免常见错误l

本文讨论了在REDIS中实施身份验证和授权,重点是实现身份验证,使用ACL以及确保REDIS的最佳实践。它还涵盖了管理用户权限和工具以增强重新安全性。

本文讨论了使用REDIS进行工作队列和背景处理,详细的设置,作业定义和执行。它涵盖了原子运营和工作优先级等最佳实践,并解释了REDIS如何提高处理效率。

本文讨论了在REDIS中实施和管理缓存无效的策略,包括基于时间的到期,事件驱动的方法和版本控制。它还涵盖了缓存到期的最佳实践和监视和自动的工具

文章讨论了使用Redis CLI,Redis Insight和Datadog和Prometheus等工具等工具进行监视REDIS群集的性能和健康。

本文讨论了在Web应用程序中使用REDIS进行会话管理,详细介绍设置,诸如可伸缩性和性能以及安全措施之类的好处。
