Redisson这个框架对Redis分布式锁的实现原理图如下:
在这里插入图片描述
加锁机制:

一个客户端A要加锁,它首先会根据hash节点选择一台机器,这里注意,仅仅只是选择一台机器。紧接着就会发送一段lua脚本到redis上,比如加锁的那个锁key就是"mylock",并且设置的时间是30秒,30秒后,mylock锁就会被释放

锁互斥机制:

如果这个时候客户端B来加锁,它也会会根据hash节点选择一台机器,然后执行了同样的一段lua脚本。
它首先回来判断"exists mylock"这个锁存在吗?如果存在,则B会获得一个数字,这个数字就是mylock这个锁的剩余生存时间,此时客户端B就会进入到一个while循环,不停的尝试加锁

watch dog自动延期机制:

客户端A加锁的锁key默认生存时间只有30秒,如果超过了30秒,客户端A还想一直持有这把锁,怎么办?其实只要客户端A一旦加锁成功,就会启动一个watch dog看门狗,它是一个后台线程,会每隔10秒检查一下,如果客户端A还持有锁key,那么就会不断的延长锁key的生存时间

可重入加锁机制:

当客户端A获得mylock锁时,里面会有一个hash结构的数据:

mylock:{"8743c9c0-0795-4907-87fd-6c719a6b4586:1":1}

这里面的8743c9c0-0795-4907-87fd-6c719a6b4586:1就是代表客户端A,数字1就是代表这个客户端加锁了一次

如果客户端A还想要持有锁mylock,那么这个1就会变成2,依次累加

释放锁机制:

如果发现加锁次数变为0了,那么说明这个客户端不再持有锁了,客户端B就可以加锁了

Redis分布式锁的缺点:

上面方案的最大问题,就是如果你对某个redis master实例,写入了myLock这种锁key的value,此时会异步复制给对应的master slave实例,但是这个过程中如果发送redis master宕机,主备切换,redis slave变为了redis master。

这就会导致客户端B来尝试加锁的时候,在新的redis master上完成了加锁,而客户端A也以为自己成功加了锁,此时就会导致多个客户端对一个分布式锁完成了加锁。这时就会导致各种脏数据的产生。

所以这个就是redis cluster,或者是redis master-slave架构的主从异步复制导致的redis分布式锁的最大缺陷:在redis master实例宕机的时候,可能导致多个客户端同时完成加锁。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐