1. go-zero 分布式锁实现
看下 go-zero 中 redis 分布式锁的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var (
lockScript = NewScript(`if redis.call("GET", KEYS[1]) == ARGV[1] then
redis.call("SET", KEYS[1], ARGV[1], "PX", ARGV[2])
return "OK"
else
return redis.call("SET", KEYS[1], ARGV[1], "NX", "PX", ARGV[2])
end`)
delScript = NewScript(`if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end`)
)
|
加锁和解锁的过程都是通过 lua 脚本实现的,因为 lua 脚本能够保证 redis 的原子性。
2. 分布式锁必须拥有的属性
- 排他性(只能有一个协程持有)
- 可重入(已经获取锁的协程能再次访问)
- 防死锁(必须有超时时间,达到后持有者自动释放)
- 高性能高可用
3. go-zero 分布式锁加锁流程
1
2
3
4
5
6
7
8
|
# 判断ARGV[1]是否等于KEY[1]的值
# 如果相等,说明是该锁的持有者重入,更新锁的过期时间,返回OK
# 如果不想等,说明锁不存在或者该用户不是锁的持有者,用set nx px命令操作该key
lockScript = NewScript(`if redis.call("GET", KEYS[1]) == ARGV[1] then
redis.call("SET", KEYS[1], ARGV[1], "PX", ARGV[2])
return "OK"
else
return redis.call("SET", KEYS[1], ARGV[1], "NX", "PX", ARGV[2])
|
4. go-zero 分布式锁解锁流程
1
2
3
4
5
6
7
|
# 判断ARGV[1]是否等于KEY[1]的值
# 如果相等,说明是锁的拥有者,删除分布式锁的KEY
# 如果不想等,说明不是锁的拥有者,返回0
delScript = NewScript(`if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
|