redis 分布式锁实现

我们实现的分布式锁,使用redis提供的SET NX功能,由于redis server的单线程模型,保证了天然并发安全。

https://stackoverflow.com/questions/11658272/is-redis-list-or-set-pop-method-thread-safe

client A通过 SET key value1 NX 获得锁,client B 不断block retry set  key value2 NX直到获得锁。(retry时间一般以十毫秒为单位,权衡了cpu占用与获取锁的及时性)

1)需要为key设置EX,防止client拿到锁后程序崩溃,锁一直得不到释放。这个值的设定要衡量实际拿到锁的业务处理时间。

2)value要使用随机生成的值,保证不重复,推荐可以使用UUID version1。目的是为不使client A处理超时,锁过期自动释放,client A误删了client B获取到的锁。

这里更好的处理方式是lock duration超过后,主动停掉正在进行的任务,因为使用锁本身即不希望代码并发执行。

3)使用的codis,防止了一台redis server的单点问题,但依然存在网络的单点。目前实现存在的缺点,但由于资源问题暂时无法解决。

1. random value

func randomValue() string {
return uuid.NewV1().String()
}

2. 获取锁

v := randomValue()
ok, err := l.client.SetNX(l.k, v, l.expiration).Result()
if err == redis.Nil {
err = nil // set failed, key already exist.
}

if err != nil {
return err // set failed, some error
} else if ok {
l.v = v
return nil
}

3. 释放锁

var rlsFunc = redis.NewScript(`
if redis.call("get", KEYS[1]) == ARGV[1] then
return
redis.call("del", KEYS[1])
else
return 0
end`)
原文地址:https://www.cnblogs.com/gm-201705/p/10087631.html