我得到了以下两个用于锁定 Redis 键的函数。我正在尝试使用 Redis 阻止并发执行一段代码。所以我所做的是以这样的方式使用以下函数,以防止不同线程执行相同的代码。
lockRedisKey("ABC");
CODE THAT I DON'T WANT TO RUN CONCURRENTLY!
unlockRedisKey("ABC");
不幸的是,它似乎不起作用并在 lockRedisKey() 处导致无限循环,直到达到 exit_time。有什么问题吗?
static public function lockRedisKey($key, $value = "true") {
$redis = RedisClient::getInstance();
$time = microtime(true);
$exit_time = $time + 10;
$sleep = 10000;
do {
// Lock Redis with PX and NX
$lock = $redis->setnx("lock:" . $key, $value);
if ($lock == 1) {
$redis->expire("lock:" . $key, "10");
return true;
}
usleep($sleep);
} while (microtime(true) < $exit_time);
return false;
}
static public function unlockRedisKey($key) {
$redis = RedisClient::getInstance();
$redis->del("lock:" . $key);
}
我知道我可能会遇到死锁,所以我决定使用事务,但我仍然面临这个问题。
static public function lockRedisKey($key, $value = "true") {
$redis = RedisClient::getInstance();
$time = microtime(true);
$exit_time = $time + 10;
$sleep = 10000;
do {
// Lock Redis with PX and NX
$redis->multi();
$redis->set('lock:' . $key, $value, array('nx', 'ex' => 10));
$ret = $redis->exec();
if ($ret[0] == true) {
return true;
}
usleep($sleep);
} while (microtime(true) < $exit_time);
return false;
}
static public function unlockRedisKey($key) {
$redis = RedisClient::getInstance();
$redis->multi();
$redis->del("lock:" . $key);
$redis->exec();
}
锁定工作正常。这只是崩溃和导致锁不被释放的锁定之间的代码:-)
你的'exit_time'太小了。 我认为'$exit_time = $time + 10;'的意思就是10秒后关机。 但是,设置的时间是微时间。
也许你可以替换'$exit_time = $time + 10;'使用“$exit_time = $time + 100000;”。 由谷歌翻译撰写
首先,PHP 不像 JS f.e. 那样是异步脚本语言。您无法控制脚本执行顺序,因此这意味着您无法以并发方式运行以下
lockRedisKey()
调用的代码。
我假设您不完全理解 usleep 函数实际上在做什么,它只是 delay 进程而不是 postpone 它,所以它只是阻止进程
$sleep
时间,然后继续执行脚本。所以你不是通过调用你的脚本来执行并发写入。