Page

【Redis】使用redis的set nx作为分布式锁

651Anson20-07-28


【Redis】使用redis的set nx作为分布式锁

官方推荐使用set nx代替setnx,因为setnx无法原子设置过期时间

if (Redis::set("my:lock", 1, "nx", "ex", 10)) {
    ... do something 
    Redis::del("my:lock") 
}


上面的代码把 my:lock 设置为 1,当且仅当这个 lock 不存在的时候,设置完成之后设置过期时间为 10。

获取锁的机制是对了,但是删除锁的机制直接使用 del 是不对的。因为有可能导致误删别人的锁的情况。

比如,这个锁我上了 10s,但是我处理的时间比 10s 更长,到了 10s,这个锁自动过期了,被别人取走了,并且对它重新上锁了。那么这个时候,我再调用 Redis::del 就是删除别人建立的锁了。


官方对解锁的命令也有建议,建议使用 lua 脚本,先进行 get,再进行 del

$token = rand(1, 100000);   # 必须保证唯一,最好使用uuid
function lock() {
    return Redis::set("my:lock", $token, "nx", "ex", 10);
}
function unlock() {
    $script = `
if redis.call("get",KEYS[1]) == ARGV[1]
then
    return redis.call("del",KEYS[1])
else
    return 0
end    
    `
    return Redis::eval($script, "my:lock", $token)
}
if (lock()) {
    // do something
    unlock();
}



来自anson博客 

http://www.tp0.top