suchen

Heim  >  Fragen und Antworten  >  Hauptteil

Predis führt zwei Befehle mithilfe von Transaktionen aus, einer davon schlägt jedoch fehl

Beschreibungsfehler

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.

Wieder auftauchen

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

Version:

Vorhersage: v2.1.2 PHP 7.4 Redis-Server 5.0.10

Codebeispiel

$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;
        }
    }
}

Andere

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.

P粉030479054P粉030479054443 Tage vor659

Antworte allen(1)Ich werde antworten

  • P粉113938880

    P粉1139388802023-09-14 11:49:51

    Redis 事务不是这样的原子事务。它们是原子的,因为在执行命令中的事务时,没有其他进程可以访问密钥空间。如果事务中的命令失败,则将执行后续命令并且不会回滚。

    例如,让我们执行一个包含错误命令的事务:

    127.0.0.1:6379> exists mylist
    (integer) 0
    127.0.0.1:6379> lpush mylist a b c
    (integer) 3
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> rpop mylist
    QUEUED
    127.0.0.1:6379> sadd mylist d
    QUEUED
    127.0.0.1:6379> expire mylist 300
    QUEUED
    127.0.0.1:6379> exec
    1) "a"
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    3) (integer) 1
    127.0.0.1:6379> ttl mylist
    (integer) 297

    这里我们检查列表是否存在,并向其中添加一些初始项目。然后,在事务中,我们从列表中弹出一个项目,错误地尝试添加一个新项目,认为键 mylist 拥有一个集合,然后设置键 mylist< 上的生存时间/代码>。第一个和第三个命令成功,最后,mylist 设置了生存时间。第二个命令失败。为此,Redis 中没有内置回滚功能 - 您的应用程序需要通过 watch 命令使用乐观锁定...这是为了在您的事务获得之前检测其他进程更改您的事务想要更改的键对服务器的独占访问。它不是回滚机制。

    详细信息:https://redis.io/docs/interact/transactions/

    Antwort
    0
  • StornierenAntwort