redistemplate加锁没设过期时间是导致死锁的最常见原因:setifabsent(key, value)不带ttl,若业务卡住或崩溃,锁永久残留;正确做法是用set(key, value, timeout, timeunit)原子设置键值与过期时间。

RedisTemplate加锁没设过期时间导致死锁
最常见死锁原因:用 setIfAbsent(key, value) 加锁,但没配 expire 或用错参数顺序。RedisTemplate 的 setIfAbsent 默认不带过期时间,一旦业务卡住或进程崩溃,锁就永远留在 Redis 里。
比如这样写就危险:
redisTemplate.opsForValue().setIfAbsent("stock:lock:1001", "client-abc");
它只保证 key 不存在时设值,但没设 TTL —— 锁不会自动释放。
- 必须显式调用
expire,且要确保两步原子性(但实际不是):先setIfAbsent,再expire,中间若崩溃,锁就漏设过期时间 - 正确做法是改用
opsForValue().set(key, value, timeout, timeUnit),这个重载方法内部用的是SET key value EX seconds NX原子命令 - 别用
setIfAbsent(key, value, timeout, timeUnit)—— 这个方法在旧版 Spring Data Redis(
解锁时误删别人锁引发连锁死锁
用 del key 直接删锁,是典型“张冠李戴”操作。A 线程加锁后执行慢,锁超时释放;B 线程抢到锁并执行;A 线程恢复后仍执行 redisTemplate.delete("stock:lock:1001"),结果把 B 的锁干掉了。
后续请求全被 B 的残留状态干扰,可能触发库存扣减错乱、重复下单等,表现就像“系统卡死”。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 解锁前必须校验 value 是否匹配:
get(key)拿当前值,equals 对比,再delete—— 但这三步非原子,高并发下仍有风险 - 生产环境必须用 Lua 脚本做原子解锁,例如:
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
- Java 中通过
redisTemplate.execute(script, keys, value)调用,value 就是加锁时传的唯一标识(如 UUID)
业务执行时间 > 锁过期时间造成“假释放”
设了 3 秒过期,但扣库存 + 写 DB + 发 MQ 耗时 5 秒,锁提前消失。其他线程趁虚而入,两个线程同时扣减,库存变负——这不是传统意义的线程阻塞死锁,但会导致数据不一致,下游服务反复重试/回滚,整体响应停滞,现象上接近死锁。
- 过期时间不能拍脑袋定,得按 P99 业务耗时 × 2 来设(比如压测发现最长 800ms,建议设 3~5 秒)
- 若业务时间波动大(如依赖外部 HTTP),必须引入看门狗机制:另起线程定期用 Lua 刷新 TTL,前提是加锁时 value 可识别归属(如拼入线程 ID 或租约 ID)
- 别依赖“锁自动过期”兜底——它只是防止单点故障,不是并发控制的主力手段
RedisTemplate 多实例共享连接池引发的隐性竞争
同一个应用里,若多个 RedisTemplate Bean 共享底层 LettuceConnectionFactory,但各自配置了不同序列化器(如一个用 StringRedisTemplate,一个用自定义 GenericJackson2JsonRedisSerializer),对同一 key 的读写可能因序列化差异导致 value 解析失败。
例如 A 用 JSON 存 "client-abc",B 用 String 序列化器读出来是乱码,比对 equals 失败,解锁逻辑直接跳过,锁滞留。
- 检查所有
RedisTemplate实例是否共用同一套序列化配置,尤其是keySerializer和valueSerializer - 锁 key 必须用字符串类型,统一走
StringRedisTemplate,避免序列化歧义 - 不要在锁 value 里塞复杂对象,只放简单唯一标识(UUID、traceId、IP+端口+线程名组合)
真正难处理的不是“锁不释放”,而是“锁被错误释放后引发的数据错乱”,它不会报错,但会让问题在下游慢慢发酵。所以加锁的 value 唯一性、解锁的原子性、过期时间与业务节奏的匹配,这三点漏掉任何一环,都可能让系统在高并发下进入不可逆的紊乱状态。










