Redis八股

关于分布式锁的代码健壮性问题

锁长期持有问题

解决方案:加过期时间

assets/Redis/file-20260803163516945.png

  • setIfAbsent()函数对应Redis的setnx方法,作用是:当 Redis 中某个 key 不存在时,才设置这个 key;如果 key 已经存在,则什么都不做。因其具有原子性,常用于做为分布式锁
    上面代码的问题:
  1. 如果代码在if/else阶段报错了,那么下面的delete将不会被执行到。也就是说,key会被建立而不会被删除。这时候如果再次由其他服务执行代码,因为Redis中存在key,即一直持有锁,setnx的修改将不会生效
    为了增强代码的健壮性,应该把其用try/finally框架包裹起来,保证锁即使在业务报错的情况下也能正常释放

assets/Redis/file-20260803164046328.png

但是这样还有一个问题,如果在执行try的时候,服务宕机了,那么finally部分仍不会被执行。所以生产常用的配置是:
SET + NX + EX
即给这个键设置过期时间。

assets/Redis/file-20260803171556508.png
设置过期时间时,不要用上面的写法,而应该使用下面的写法。
因为上面的写法不具有原子性,如果服务宕机,可能会出现过期时间设置失败的情况。
而下面的写法是在设置键时,一并设置过期时间,具有原子性

服务延迟,超过了过期时间问题

解决方案:锁续期

业务逻辑描述:例如把锁的过期时长设置为30秒(在这里指字段的过期时间,因为通过setnx实现了分布式锁的功能)。然后在业务代码里开一条子线程,每10秒检测一次加锁情况。如果还持有锁,就重置锁的过期时间。这样可以保证在业务代码正常运行期间,锁不会过期。而业务代码结束后,子线程会自然结束掉。也就不会再重置锁的过期时长,业务结束会主动释放锁,及时失败,锁也会自动过期

(已经有完善的开源实现框架:redisson

posted @ 2026-08-03 18:37  畅畅c  阅读(3)  评论(0)    收藏  举报