Ich verwende eine Redis-Liste, um einen Begrenzer zu erstellen, und es funktioniert die meiste Zeit wie erwartet, aber kürzlich habe ich festgestellt, dass es einige Schlüssel gibt, die keine Ablaufzeit haben. Idealerweise würde ich die Werte in die Liste „rpushen“ und die Ablaufzeit in einer Transaktion festlegen und ich würde auch „watch“ verwenden, bevor die Transaktion beginnt.
Dieser Fehler tritt in meiner lokalen Umgebung nicht erneut auf, selbst wenn ich Jmeter verwende, um verwandte APIs stapelweise anzufordern, beispielsweise 500 Anfragen in 1 Sekunde
Vorhersage: v2.1.2 PHP 7.4 Redis-Server 5.0.10
$redisClient->watch($key); $current = $redisClient->llen($key); // Transaction start $tx = $redisClient->transaction(); if ($current >= $limitNum) { $redisClient->unwatch(); return false; } else { if ($redisClient->exists($key)) { $tx->rpush($key, $now); try { $replies = $tx->execute(); return true; } catch (\Exception $e) { return false; } } else { // Using transaction to let rpush and expire to be an atomic operation $tx->rpush($key, $now); $tx->expire($key, $expiryTime); try { $replies = $tx->execute(); return true; } catch (\Exception $e) { return false; } } }
Dies ist der erwartete Vorgang auf meinem lokalen Redis-Server
Redis-Transaktionen sind atomar. Atomar bedeutet, dass entweder alle Befehle verarbeitet werden oder keine Befehle verarbeitet werden. In meinem Fall sollte ein Schlüssel also ein Ablaufdatum haben.
Redis 事务不是这样的原子事务。它们是原子的,因为在执行命令中的事务时,没有其他进程可以访问密钥空间。如果事务中的命令失败,则将执行后续命令并且不会回滚。
例如,让我们执行一个包含错误命令的事务:
这里我们检查列表是否存在,并向其中添加一些初始项目。然后,在事务中,我们从列表中弹出一个项目,错误地尝试添加一个新项目,认为键
mylist
拥有一个集合,然后设置键mylist。第一个和第三个命令成功,最后,
mylist
设置了生存时间。第二个命令失败。为此,Redis 中没有内置回滚功能 - 您的应用程序需要通过watch
命令使用乐观锁定...这是为了在您的事务获得之前检测其他进程更改您的事务想要更改的键对服务器的独占访问。它不是回滚机制。详细信息:https://redis.io/docs/interact/transactions/