Redis实现分布式锁的演进思路

相关概念:Redis

Redis 分布式锁最容易踩坑的地方,不是“怎么写出第一版”,而是“第一版为什么很快就不够用”。

第一步:只有单机锁不够

如果服务部署在多个 JVM 上,synchronized 只能保护单进程内的线程,挡不住多机并发。

这时才有必要把锁状态放到 Redis 里。

第二步:至少要有超时

最简单的写法,是用 SETNX 一类语义去抢锁,并顺手加上过期时间。

没有过期时间的问题很直接:

  • 线程拿到锁后崩了
  • 锁永远不释放
  • 其他请求全部卡死

第三步:解锁必须有归属校验

只有“谁加的锁,谁才能解”才算像样的分布式锁。

否则一个无关线程误删锁,就会让临界区重新暴露在并发写入下。

常见做法是:

  • 加锁时写入线程唯一标识
  • 解锁时先比对标识,再决定是否删除

第四步:要考虑可重入

如果同一线程在方法嵌套调用里反复进入临界区,锁需要支持可重入。

不然会出现两类问题:

  • 再次加锁失败,导致本线程把自己拦住
  • 内层方法提前解锁,导致外层逻辑在无锁状态下继续执行

一个实用思路是:

  • Redis 里只保存锁归属
  • 线程内再额外维护重入计数

这还不是终点

就算做到了“超时 + 归属 + 可重入”,离生产可用通常还差一截,至少还要继续考虑:

  • 解锁是否原子,避免“先判断后删除”被并发穿透
  • 业务执行时间超过 TTL 时是否需要续期
  • 锁粒度是否过粗
  • 主从切换时是否存在锁丢失窗口

结论

Redis 很适合用来理解分布式锁的基本机制,但真正进生产,通常更应该优先用成熟实现,而不是手搓一个“差不多能跑”的版本。