redis-简单分布式锁

2020-04-03  本文已影响0人  GGBond_8488

在Redis中有一个 setnx key value命令,这个命令只能在key不存在时才能执行成功,因此,可以利用该特性构建一个分布式锁。

这里以一个秒杀系统需求下的场景来探索redis分布式锁

Version1

使用setnx object_id_1 value(随机value)获取锁,完成操作del object_id_1释放锁
这个版本问题很多,非常明显的就是,若是加锁的线程意外崩溃(并未执行释放锁操作),那么其他线程永远也无法获得该锁。
(在go中可以使用defer来收尾,确保释放锁)
但是,有很多其他情况使得无法执行到释放锁操作(服务器down机)
但是redis里该锁还是未被释放

Version2

加锁时,给其也设置一个超时时间(这里保证原子操作)。
SET object_id_1 random_value NX PX 5000
这种情况下,如果时间设置过短,低于业务真正执行时间,那么可能就会出现这样的问题,

线程1获得锁,执行业务代码,(此时锁自动过期) -- 这时线程1执行完毕释放锁
------------------------------------------此时业务2可以获得该锁,执行业务2的代码

那么这里线程1就把线程2加的锁给释放掉了,后来的更多线程都能获得锁,分布式锁直接失效

这里的问题:

1.过期时间设置问题
2.线程可以释放其他线程的锁

解决1:该线程获得锁以后,开辟一个新的线程,给锁保活,增加其过期时间。
解决2:每一个线程使用自己生成的全局唯一uuid来作为锁的value(使用LUA脚本完成这一操作,先判断当前锁的字符串是否与传入的值相等,是的话就删除Key,)

但是这里在主从模式下,主服务器down掉,setnx并未传递到从机,当从机提升为主机时
可以设置(保证从结点加锁成功才会返回成功)

若是cluster情况下,可以使用官方建议的redlock(这个好像有争议)

上一篇下一篇

猜你喜欢

热点阅读