大白话快速讲懂Redis分布式锁

技术的演变都是为了解决问题的,这也是技术演变吸引人的一点。

Redis分布式锁

分布式锁顾名思义 就是在分布式场景下 多台机器竞争一项资源去加锁

最简单的版本

首先就是最简单的版本,可以通过Redis的setnx命令(set if not exist)

setnx key value

这个命令会使Redis中如果不存在key就会创建值为value的key,存在的话就返回0

image.png

过期时间

如果获取锁的机器服务挂了呢?

image.png

其他机器:奶奶滴 怎么还不释放锁?

所以 有个兜底策略: 设置过期时间(挂了之后过段时间锁自动过期释放了)

此时可以用一个Redis自带的原子性的操作命令:

setnx key value nx ex 100

时间单位是秒

万一释放错锁了怎么办?

看这么一个场景:

image.png

涉及到两个问题:

  1. 任务还没处理完锁就过期释放了
  2. 释放掉了别人的锁

对应的解决办法:

  1. 锁的续约(根据业务加长时间,并且每过一段时间访问锁,如果存在就续约,增加时间)
  2. 给每个锁区分一下,这是谁加的锁(锁的value可以设置UUID等唯一确定的值)

优化过后的:

image.png

lua实现原子性

上面的一步删除的时候会发生什么错误?

image.png

当然 这个问题上面已经解决了,就是UUID+线程id作为key,已经不会被其他线程删掉了,但是这么看来这种错误也是挺危险的,作为一个兜底方案,我们可以用lua脚本实现原子性

lua脚本可以这么写

7e5cc0a8898c93381a90dbb81b414cc8.png

最后的防御

当然分布式的NPC原则告诉我们,没有完全安全的分布式锁(所以大家还是要根据业务来)

上面的场景中,主节点挂了咋办?

因为Redis是AP架构的,也就是说不能保证高一致性,主节点里的锁也许并没有同步到从节点里

这里可以用Redis官方的Red Lock 保证当前hash算法选择的节点的主从都有key了才会返回true

这种做法也有点“重”了,有些时候,杀鸡焉用牛刀

猜你喜欢

转载自juejin.im/post/7255902957035323450