推荐链接:
总结——》【Java】
总结——》【Mysql】
总结——》【Redis】
总结——》【Kafka】
总结——》【Spring】
总结——》【SpringBoot】
总结——》【MyBatis、MyBatis-Plus】
总结——》【Linux】
总结——》【MongoDB】
总结——》【Elasticsearch】
Redis——》死锁
一、死锁场景
// 加锁
SETNX lock_key 1
// 业务逻辑
DO THINGS
// 释放锁,删除key
DEL lock_key
以下情况会导致已经获得锁的客户端一直占用锁,其他客户端永远无法获取到锁,这就是死锁:
- 程序处理业务逻辑异常,没及时释放锁
- 进程挂了,没机会释放锁
二、如何避免死锁
方案:给锁设置一个过期时间
示例:假设操作共享资源的时间不会超过10s,那么加锁时,给这个key设置10s过期。
1、两条命令实现:SETNX加锁 + EXPIRE过期时间
(1)实现
SETNX lock_key 1 // 加锁
EXPIRE lock_key 10 // 10s后自动过期
(2)优点
锁可以被自动释放,其它客户端依旧可以拿到锁
(3)缺点
如果过期时间设置失败,依旧发生死锁问题。
原因:
加锁、设置过期时间是2条命令,这2条命令不能保证是原子操作(一起成功),有可能只执行了第一条,第二条却执行失败
场景:
- SETNX执行成功,执行EXPIRE时由于网络问题,执行失败
- SETNX执行成功,Redis异常宕机,EXPIRE没有机会执行
- SETNX执行成功,客户端异常崩溃,EXPIRE没有机会执行
2、一条命令实现:SET加锁 + EXPIRE过期时间
在Redis 2.6.12之后,Redis扩展了SET命令的参数,可以在SET的同时指定EXPIRE时间,这条操作是原子的。
(1)实现
SET lock_key 1 EX 10 NX // 10s后自动过期
(2)优点
解决死锁问题
(3)缺点
可能发生释放别人的锁(参考链接:Redis——》锁被别人释放)