时间:2021-07-01 10:21:17 帮助过:5人阅读
$lock_num = 0;
while(!redis_helper::lock("lottery")) {
if($lock_num >= 300) {
return "亲,好多人在排队抢红包啊,请重新进入页面";
}
// 0.1s
usleep(100000);
$lock_num ++;
}
下面是并发锁定的相关函数, 自己能明白这个锁每6s会变换一次真假值,但是不明白结合上面的$lock_num针对的并发情况到底是啥? 没6s变换真假值,6s/0.1s = 60次,怎么会达到300,页面卡住了,其他人恰好重新将锁设置为假?
/**
* 并发锁定
* @param string $name 锁名称
* @param int $expires 超时失效的时间,单位秒
* @return bool true:获取锁成功,false:获取锁失败
*/
public static function lock($name, $expires = 5)
{
self::init_redis();
$key = $name . '_lock';
$now = time();
$val = $now + $expires + 1;
if(self::$redis->setnx($key, $val)) {
return true;
} else {
$old_val = self::$redis->get($key);
// 失效的情况
if($now > $old_val && $now > self::$redis->getSet($key, $val)) {
return true;
}
}
return false;
}
自己见过的锁都是类似先定义一个变量 = true, 相关操作完成之后再把相关的值变成false.
$lock_num = 0;
while(!redis_helper::lock("lottery")) {
if($lock_num >= 300) {
return "亲,好多人在排队抢红包啊,请重新进入页面";
}
// 0.1s
usleep(100000);
$lock_num ++;
}
下面是并发锁定的相关函数, 自己能明白这个锁每6s会变换一次真假值,但是不明白结合上面的$lock_num针对的并发情况到底是啥? 没6s变换真假值,6s/0.1s = 60次,怎么会达到300,页面卡住了,其他人恰好重新将锁设置为假?
/**
* 并发锁定
* @param string $name 锁名称
* @param int $expires 超时失效的时间,单位秒
* @return bool true:获取锁成功,false:获取锁失败
*/
public static function lock($name, $expires = 5)
{
self::init_redis();
$key = $name . '_lock';
$now = time();
$val = $now + $expires + 1;
if(self::$redis->setnx($key, $val)) {
return true;
} else {
$old_val = self::$redis->get($key);
// 失效的情况
if($now > $old_val && $now > self::$redis->getSet($key, $val)) {
return true;
}
}
return false;
}
我的理解是尝试300次获取锁,如果失败了,就告诉用户失败。
成功获取锁的话,有6秒的独占时间。这个时间用来给程序处理后续的业务逻辑,比如生成订单。6秒过后,下一个用户进来,继续获取锁。
lock ->do sth. ->release
lock ->do sth. ->release
lock ->do sth. ->release
lock ->do sth. ->release
$lock_num跟锁没有关系,$lock_num只是用来记录重试的次数,比如当前同时有1000个用户在抢这个锁,而你如果重试了300次(30秒)还没有抢到锁就待会再来吧。
循环会每隔0.1秒重试一次,但是因为一个锁会占用6秒的时间,所以实际上在300次循环中(30秒)其实只有5次竞争锁的机会。