Predis exécute deux commandes à l'aide de transactions, mais l'une d'elles échoue
P粉030479054
P粉030479054 2023-09-13 17:55:41
0
1
569

Erreur de description

J'utilise une liste Redis pour créer un limiteur et cela fonctionne comme prévu la plupart du temps, mais récemment j'ai découvert que certaines clés n'ont pas de délai d'expiration. Idéalement, je "pousserais" les valeurs dans la liste et définirais l'heure d'expiration dans une transaction et j'utiliserais également "watch" avant le début de la transaction.

Réapparaître

Ce bug ne se reproduit pas dans mon environnement local, même si j'utilise jmeter pour requêter par lots les API associées, telles que 500 requêtes en 1 seconde

Version :

Prédiction : v2.1.2 PHP7.4 Serveur Redis 5.0.10

Exemple de code

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

Autres

C'est l'opération attendue sur mon serveur Redis local

Les transactions Redis sont atomiques. Atomique signifie que soit toutes les commandes sont traitées, soit aucune commande n'est traitée. Donc dans mon cas, une clé doit avoir une date d'expiration.

P粉030479054
P粉030479054

répondre à tous(1)
P粉113938880

Les transactions Redis ne sont pas de telles transactions atomiques. Ils sont atomiques car aucun autre processus ne peut accéder à l'espace clé pendant l'exécution des transactions de la commande. Si une commande au sein d'une transaction échoue, les commandes suivantes seront exécutées et ne seront pas annulées.

Par exemple, exécutons une transaction qui contient la mauvaise commande :

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

Ici, nous vérifions si la liste existe et y ajoutons quelques éléments initiaux. Ensuite, au cours de la transaction, nous supprimons un élément de la liste et essayons par erreur d'ajouter un nouvel élément en pensant que la commande clé mylist 拥有一个集合,然后设置键 mylist。第一个和第三个命令成功,最后,mylist 设置了生存时间。第二个命令失败。为此,Redis 中没有内置回滚功能 - 您的应用程序需要通过 watch utilise le verrouillage optimiste... Il s'agit de détecter les modifications apportées par d'autres processus avant que votre transaction n'obtienne ce qu'elle veut. La clé modifiée a un accès exclusif au serveur. Il ne s'agit pas d'un mécanisme de restauration.

Détails : https://redis.io/docs/interact/transactions/

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!