1. Présentation :
Comme beaucoup d'autres bases de données, Redis en tant que base de données NoSQL fournit également un mécanisme de transaction. Dans Redis, les quatre commandes MULTI/EXEC/DISCARD/WATCH sont la pierre angulaire de notre implémentation de transactions. Je pense que ce concept n'est pas étranger aux développeurs ayant une expérience en développement de bases de données relationnelles. Néanmoins, nous énumérerons brièvement les caractéristiques d'implémentation des transactions dans Redis :
1) Dans les transactions, toutes les commandes seront exécutées en série et séquentiellement. Pendant l'exécution de la transaction, Redis ne fournira aucun service pour les autres demandes des clients, garantissant ainsi que toutes les commandes de la transaction sont exécutées de manière atomique.
2). Par rapport aux transactions dans les bases de données relationnelles, si une commande ne parvient pas à s'exécuter dans une transaction Redis, les commandes suivantes continueront d'être exécutées.
3). Nous pouvons démarrer une transaction via la commande MULTI, que les personnes ayant de l'expérience dans le développement de bases de données relationnelles peuvent comprendre comme l'instruction "BEGIN TRANSACTION". Les commandes exécutées après cette instruction seront considérées comme des opérations au sein de la transaction. Enfin, nous pouvons valider/annuler toutes les opérations au sein de la transaction en exécutant la commande EXEC/DISCARD. Ces deux commandes Redis peuvent être considérées comme équivalentes à l'instruction COMMIT/ROLLBACK dans une base de données relationnelle.
4). Avant le démarrage de la transaction, s'il y a un échec de communication entre le client et le serveur et que le réseau est déconnecté, toutes les instructions ultérieures à exécuter ne seront pas exécutées par le serveur. Cependant, si l'événement d'interruption du réseau se produit après que le client a exécuté la commande EXEC, toutes les commandes de la transaction seront exécutées par le serveur.
5). Lors de l'utilisation du mode Append-Only, Redis écrira toutes les opérations d'écriture de la transaction sur le disque lors de cet appel en appelant la fonction système write. Cependant, si une panne du système se produit pendant le processus d'écriture, telle qu'un temps d'arrêt provoqué par une panne de courant, seule une partie des données peut être écrite sur le disque à ce moment-là, tandis qu'une autre partie des données est perdue. Le serveur Redis effectuera une série de vérifications de cohérence nécessaires lors du redémarrage. Une fois qu'un problème similaire est détecté, il se fermera immédiatement et affichera une invite d'erreur correspondante. À l'heure actuelle, nous devons utiliser pleinement l'outil redis-check-aof fourni dans la boîte à outils Redis. Cet outil peut nous aider à localiser les erreurs d'incohérence des données et à restaurer certaines des données écrites. Après la réparation, nous pouvons redémarrer le serveur Redis.
2. Liste des commandes associées :
命令原型 | 时间复杂度 | 命令描述 | 返回值 |
MULTI | 用于标记事务的开始,其后执行的命令都将被存入命令队列,直到执行EXEC时,这些命令才会被原子的执行。 | 始终返回OK | |
EXEC | 执行在一个事务内命令队列中的所有命令,同时将当前连接的状态恢复为正常状态,即非事务状态。如果在事务中执行了WATCH命令,那么只有当WATCH所监控的Keys没有被修改的前提下,EXEC命令才能执行事务队列中的所有命令,否则EXEC将放弃当前事务中的所有命令。 | 原子性的返回事务中各条命令的返回结果。如果在事务中使用了WATCH,一旦事务被放弃,EXEC将返回NULL-multi-bulk回复。 | |
DISCARD | 回滚事务队列中的所有命令,同时再将当前连接的状态恢复为正常状态,即非事务状态。如果WATCH命令被使用,该命令将UNWATCH所有的Keys。 | 始终返回OK | |
WATCHkey [key ...] | O(1) | 在MULTI命令执行之前,可以指定待监控的Keys,然而在执行EXEC之前,如果被监控的Keys发生修改,EXEC将放弃执行该事务队列中的所有命令。 | 始终返回OK。 |
UNWATCH | O(1) | 取消当前事务中指定监控的Keys,如果执行了EXEC或DISCARD命令,则无需再手工执行该命令了,因为在此之后,事务中所有被监控的Keys都将自动取消。 | 始终返回OK。 |
3. Exemples de commandes :
1. La transaction est exécutée normalement :
#在Shell命令行下执行Redis的客户端工具。 /> redis-cli #在当前连接上启动一个新的事务。 redis 127.0.0.1:6379> multi OK #执行事务中的第一条命令,从该命令的返回结果可以看出,该命令并没有立即执行,而是存于事务的命令队列。 redis 127.0.0.1:6379> incr t1 QUEUED #又执行一个新的命令,从结果可以看出,该命令也被存于事务的命令队列。 redis 127.0.0.1:6379> incr t2 QUEUED #执行事务命令队列中的所有命令,从结果可以看出,队列中命令的结果得到返回。 redis 127.0.0.1:6379> exec 1) (integer) 1 2) (integer) 1
2. Il y a une commande qui a échoué dans la transaction :
#开启一个新的事务。 redis 127.0.0.1:6379> multi OK #设置键a的值为string类型的3。 redis 127.0.0.1:6379> set a 3 QUEUED #从键a所关联的值的头部弹出元素,由于该值是字符串类型,而lpop命令仅能用于List类型,因此在执行exec命令时,该命令将会失败。 redis 127.0.0.1:6379> lpop a QUEUED #再次设置键a的值为字符串4。 redis 127.0.0.1:6379> set a 4 QUEUED #获取键a的值,以便确认该值是否被事务中的第二个set命令设置成功。 redis 127.0.0.1:6379> get a QUEUED #从结果中可以看出,事务中的第二条命令lpop执行失败,而其后的set和get命令均执行成功,这一点是Redis的事务与关系型数据库中的事务之间最为重要的差别。 redis 127.0.0.1:6379> exec 1) OK 2) (error) ERR Operation against a key holding the wrong kind of value 3) OK 4) "4"
#为键t2设置一个事务执行前的值。 redis 127.0.0.1:6379> set t2 tt OK #开启一个事务。 redis 127.0.0.1:6379> multi OK #在事务内为该键设置一个新值。 redis 127.0.0.1:6379> set t2 ttnew QUEUED #放弃事务。 redis 127.0.0.1:6379> discard OK #查看键t2的值,从结果中可以看出该键的值仍为事务开始之前的值。 redis 127.0.0.1:6379> get t2 "tt"
4. Commande WATCH et verrouillage optimiste basé sur CAS :
Dans les transactions Redis In, la commande WATCH peut être utilisée pour fournir la fonctionnalité CAS (check-and-set). Supposons que nous surveillons plusieurs clés via la commande WATCH avant l'exécution de la transaction. Si la valeur d'une clé change après WATCH, la transaction exécutée par la commande EXEC sera abandonnée et une réponse multi-bulk Null sera renvoyée pour informer l'appelant. de la transaction. Par exemple, nous supposons encore que la commande incr n'est pas fournie dans Redis pour compléter l'incrément atomique des valeurs clés. Si nous voulons implémenter cette fonction, nous ne pouvons écrire que nous-mêmes le code correspondant. Le pseudo code est le suivant :
val = GET mykey val = val + 1 SET mykey $val
Le code ci-dessus ne peut garantir que le résultat de l'exécution est correct dans le cas d'une seule connexion, car s'il y a plusieurs clients exécutant cette section au même moment en même temps, code, alors il y aura un scénario d'erreur qui se produit souvent dans les programmes multithread-condition de concurrence (condition de concurrence). Par exemple, les clients A et B lisent la valeur originale de mykey en même temps. Supposons que la valeur soit 10. Après cela, les deux clients en ajoutent un à la valeur et la redéfinissent sur le serveur Redis. de mykey à perdre. Le résultat est 11, pas 12 comme nous le pensions. Afin de résoudre des problèmes similaires, nous avons besoin de l'aide de la commande WATCH, voir le code suivant :
WATCH mykey val = GET mykey val = val + 1 MULTI SET mykey $val EXEC
La différence avec le code précédent est que le nouveau code surveille la clé via la commande WATCH avant d'obtenir la valeur de mykey , puis entourez la commande set dans une transaction, ce qui peut effectivement garantir qu'avant d'exécuter EXEC pour chaque connexion, si la valeur de mykey obtenue par la connexion actuelle est modifiée par d'autres clients connectés, la commande EXEC du courant la connexion ne parviendra pas à s'exécuter. De cette façon, l'appelant peut savoir si val a été réinitialisé avec succès après avoir jugé la valeur de retour.
Ce qui précède est le contenu du didacticiel Redis (8) : Transactions détaillées. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (m.sbmmt.com) !