您的位置:首页 > 数据库 > Redis

用Redis的set指令实现锁

2016-06-25 11:01 537 查看
本文参考了http://huoding.com/2015/09/14/463

我们知道,现在的Redis实现加锁的方法比较简单,直接调用Redis的set指令:

$redis->set($key, $random, array('nx', 'ex' => $expire));
就可以实现。其中$random是个随机值,nx表示如果Redis中不存在$key时,就设置$key,ex表示设置超时,$expire表示超时的值。

但是,解锁的方法稍微复杂些。

今天跟同事讨论问题时,发现文章开头的链接中给出的方法仍然有问题,有下面这种情况:

假设现在有两个进程,分别是A和B。A在执行到:

if ($redis->get($key) == $random) {
$redis->del($key);
}

中$redis->del($key);之前,恰好$key超时,而假设此时B刚好调用set设置好$key,然后A再执行$redis->del($key);即A把B设置的$key删除掉了。要解决这个问题,只有使用watch/multi/exec来解决,即Redis在某个进程的“事务”中watch某个$key后,在multi和exec之间,如果$key被另外一个进程修改,那么当前进程试图对它的操作无效。

现在将代码修改为:

$redis->watch($key);
$redis->multi();

if ($redis->get($key) == $random) { $redis->del($key); }

$redis->exec();


如果A执行完比较操作后,$key刚好超时,B再调用set,那么由于$key的值被修改过,所以$redis->del($key);失效;如果A执行完比较操作后,$key没有超时,这时候B执行set操作是会失败的,从而$redis->del($key)删除的是A之前设置的记录。解决问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: