Implementieren Sie den Sperrmechanismus mit PHPRedis
P粉515066518
2023-08-28 18:33:09
<p>Ich habe die folgenden zwei Funktionen zum Sperren des Redis-Schlüssels erhalten. Ich versuche, die gleichzeitige Ausführung eines Codeblocks mithilfe von Redis zu verhindern. Deshalb habe ich die folgende Funktion verwendet, um zu verhindern, dass verschiedene Threads denselben Code ausführen. </p>
<pre class="brush:php;toolbar:false;">lockRedisKey("ABC");
CODE, DEN ICH NICHT GLEICHZEITIG AUSFÜHREN MÖCHTE!
unlockRedisKey("ABC");</pre>
<p>Leider scheint es nicht zu funktionieren und führt dazu, dass lockRedisKey() eine Endlosschleife durchführt, bis exit_time erreicht ist. Was könnte möglicherweise falsch laufen? </p>
<pre class="brush:php;toolbar:false;">statische öffentliche Funktion lockRedisKey($key, $value = "true") {
$redis = RedisClient::getInstance();
$time = microtime(true);
$exit_time = $time + 10;
$sleep = 10000;
Tun {
// Redis mit PX und NX sperren
$lock = $redis->setnx("lock:" . $key, $value);
if ($lock == 1) {
$redis->expire("lock:" . $key, "10");
return true;
}
usleep($sleep);
} while (microtime(true) < $exit_time);
falsch zurückgeben;
}
statische öffentliche Funktion unlockRedisKey($key) {
$redis = RedisClient::getInstance();
$redis->del("lock:" . $key);
}</pre>
<p>Ich wusste, dass es zu einem Deadlock kommen könnte, also habe ich mich für die Verwendung von Transaktionen entschieden, aber ich stehe immer noch vor diesem Problem. </p>
<pre class="brush:php;toolbar:false;">statische öffentliche Funktion lockRedisKey($key, $value = "true") {
$redis = RedisClient::getInstance();
$time = microtime(true);
$exit_time = $time + 10;
$sleep = 10000;
Tun {
// Redis mit PX und NX sperren
$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);
falsch zurückgeben;
}
statische öffentliche Funktion unlockRedisKey($key) {
$redis = RedisClient::getInstance();
$redis->multi();
$redis->del("lock:" . $key);
$redis->exec();
}</pre></p>
您的“exit_time”太小。 我认为'$exit_time = $time + 10;'的含义10秒后将其关闭。 不过,设定的时间是微时间。
也许你可以替换 '$exit_time = $time + 10;'与“$exit_time = $time + 100000;”。 由谷歌翻译撰写
锁定工作正常。这只是锁定之间的代码崩溃并导致锁定无法释放:-)