Redis 分布式锁

分布式锁实际上就是 synchronized 关键字,在同一时间,只能有一个线程,进入当前 同步 代码块 (修改数据)

在 redis 中一般使用 setnx (set if not exists) 指令实现,通常会搭配 del 和 TTL 使用

如果 setnx 返回 1 ,证明当前无人占用,为了避免 del 之前发生异常,导致没有正确删除,会使用 TTL 设置过期时间

当锁存在时 (已经被人占用)

可是如果 expire 指令也没有得到正确执行呢?

Redis 2.8 版本中加入了一个 可以将 set 和 expire 合并的 原子操作

set lock_hello world ex 600 nx

如果没有抢到 锁 , 会得到一个 nil

如果逻辑代码的执行时间特别的长,而且不稳定,那对于锁的 TTL 就要慎重考虑

例如:

  1. 张三持有了 锁
  2. 张三设置 TTL 10分钟
  3. 张三开始执行逻辑 ( 没有完成,执行中…)
  4. 10分钟到了
  5. 锁自动释放了 (张三的逻辑还没有执行完)
  6. 李四拿到了锁
  7. 李四执行逻辑
  8. 李四释放了锁 (这个锁是张三创建的)

这里有两个问题

  1. 李四在张三的逻辑结束之前拿到了 不应该 拿到的锁
  2. 李四释放了张三的锁

对于第二个问题可以通过将 local_key 的 value 值 设置成 随机数 来解决

张三 放入 随机数 5323 , 李四的 setnx 并不会改变这个值 (设置如果不存在),那么李四在del之前需要比较这个值是否与自己 setnx 的值一致,来决定是否删除这个值,这样每个 锁 都只能由 创建者 删除,或者 TTL 超时由系统删除

Send a Message