分布式锁——redis实现
在微服务盛行的今天,分布式锁也就不可避免的要经常用到,通过查看redisson官网,对部分内容进行一个梳理。
加锁机制
客户端需要加锁,面对一个redis集群,先根据hash节点选择一台机器,然后发送lua脚本到redis上面,可以保证复杂业务逻辑的原子性, 当lua脚本执行完获取锁后,客户端2如果再来尝试加锁,会发现已经存在这个锁,有对应的客户端1的id,他会获得这个锁的剩余生存时间,while循环不断加锁。
dog机制
客户端加锁默认生存时间30s,一旦加锁成功会有一个dog线程,10s检查一次如果客户端还持有锁,会不断延长锁key的生存时间。
可重入锁机制
如果客户端1已经持有这把锁,又进行可重入的加锁,这时脚本会检查出已经有这个锁,但对应的id是自己的客户端id,这时就会执行可重入加锁的逻辑,对客户端的加锁次数,累加1,数据结构大概如下:
锁释放机制:
每次都对锁的加锁次数-1,如果为0,则del掉,删除这个key,其他的客户端就可以完成加锁操作了;
问题:
- 对于客户端持有锁后宕机导致死锁的问题,dog机制已经解决了这个问题;
- 在redis集群主从的这种搭建中,会带来另外一个问题:说白了还是CAP原则,分布式可用性和一致性不可能同时满足:假如client1对redis主获取了锁,然后异步复制给了redis从,如果这时redis主宕机,redis从变为主,就会导致client2来加锁的时候,成功加锁,则破坏了分布式锁的原则,导致多个线程对一个分布式锁完成了加锁,脏数据就会由此产生。
参考:掘金