分布式锁
来自智得网
简介
在单机环境下,锁一般通过CAS方式实现,通过锁定的时机或者范围一般分为悲观锁和乐观锁,在操作开始之前执行锁定操作一定成为称之为悲观锁,在提交的时候才可以加锁进行校验成为乐观锁。
在集群环境下,本机锁无法和集群内其他节点实现互斥,会出现业务逻辑错误,分布式锁就是集群场景下可以实现互斥能力的结构体。
原理
锁的实现例如CAS本质上还是通过修改共享数据来实现的,所以分布式锁的本质也是修改分布式场景下的共享数据。
根据共享数据的不同,分布式锁可以通过Redis,数据库,Zookeeper等实现。
Redis
Redis锁的实现方式是通过Redis客户端向Redis写入数据的方式的方式,通过CAS实现写入的原子性来保证分布式锁实现的。
Redis加锁的命令一般是
//使用unique_value作为唯一性标识进行加锁操作
//NX的含义是set为setnx(SET if not exist),实现原子性
//PX的含义是key的失效时间(分布式锁自动解锁的时间),避免手动解锁失败而长期hang住
SET lock_key unique_value NX PX 10000
Redis解锁的命令一般是
//ARGV[1]是加锁时候的唯一key,避免锁被其他线程释放
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
Redis分布式锁的问题如下,当Master节点不可用的时系统自动切换Slave(failover),但由于Redis的主从复制(replication)异步的原因,可能导致在failover过程中丧失锁的安全性。例如下面场景的客户端1和客户端2同时持有了同一个资源的锁。
- 客户端1从Master获取了锁。
- Master宕机,存储锁的key还未同步到Slave。
- Slave升级为Master。
- 客户端2从新Master获取到了对应同一个资源的锁。
RedLock
RedLock的加锁流程如下:
- 客户端向N个Redis实例执行加锁操作,统计总耗时为TotalCost
- 超过半数节点实例成功获取锁,并且锁的有效期大于TotalCost才表明加锁成功
- 若加锁失败,则释放已成功获取的锁。
- 若加锁成功,锁的有效时间=锁的超时时间-TotalCost