Maîtrise des commandes Redis GET et SET : Opérations de données de base

Maîtrisez les fondamentaux de la gestion des données Redis avec ce guide complet des commandes `GET` et `SET`. Apprenez le stockage et la récupération de base des chaînes, et explorez les options avancées essentielles comme la définition atomique (`NX`/`XX`) et l'expiration intégrée des clés (`EX`/`PX`). Découvrez comment ces commandes fondamentales sont cruciales pour construire des couches de mise en cache hautes performances.

Maîtrise des commandes Redis GET et SET : Opérations de données de base

Les commandes Redis GET et SET semblent presque trop simples. Écrire une valeur. Lire une valeur. Dans les applications réelles, ces deux commandes se cachent derrière les sessions de connexion, les indicateurs de fonctionnalités, les limites de débit, les entrées de cache, les verrous de courte durée et les raccourcis "ne pas interroger à nouveau la base de données".

Les détails comptent car Redis fait exactement ce que vous demandez. Si vous écrasez accidentellement une clé, il ne vous demandera pas si vous le vouliez. Si vous oubliez une expiration sur des données de cache, elles peuvent vivre plus longtemps que la source de données. Si vous traitez une clé manquante de la même manière qu'une chaîne vide, votre application peut prendre la mauvaise décision.

Le modèle clé-valeur Redis

Avant de plonger dans les commandes, il est important de se rappeler que Redis fonctionne sur un modèle simple de magasin clé-valeur. Chaque donnée (la valeur) est accessible à l'aide d'un identifiant unique (la clé). Les clés sont des chaînes, et les valeurs peuvent être de différents types de données (chaînes, listes, ensembles, hachages, etc.). SET et GET traitent principalement du type de données Chaîne, qui est le type le plus basique et le plus fréquemment utilisé dans Redis.

1. Définir des données : La commande SET

La commande SET est utilisée pour attribuer une valeur à une clé. Si la clé contient déjà des données, la commande SET écrasera la valeur existante. Sa syntaxe de base est simple.

Syntaxe de base et utilisation

La forme la plus simple nécessite uniquement la clé et la valeur :

SET key value

Exemple : stocker le nom d'affichage d'un utilisateur :

127.0.0.1:6379> SET user:100:name "Alice Johnson"
OK

127.0.0.1:6379> GET user:100:name
"Alice Johnson"

Options avancées de SET : NX, XX et expiration

La puissance de SET vient de ses arguments optionnels, qui permettent une définition conditionnelle atomique et une gestion du temps de vie (TTL). Ces options sont essentielles pour implémenter correctement les verrous et les caches.

Définition conditionnelle : NX et XX

Ces options contrôlent quand une opération de définition se produit, empêchant les écrasements accidentels ou garantissant qu'un écrasement se produit uniquement si la clé existe.

  • NX (N'existe pas) : Définir la clé uniquement si elle n'existe pas déjà. Utile pour les opérations "création uniquement" et les modèles de verrouillage simples.

    SET my_lock_key some_unique_value NX
    
  • XX (Existe) : Définir la clé uniquement si elle existe déjà. Utile lorsque vous souhaitez rafraîchir une clé connue sans en créer accidentellement une nouvelle.

    SET session:token:456 new_value XX
    

B. Définition du temps d'expiration (TTL)

Pour gérer la mémoire et implémenter une mise en cache basée sur le temps, vous pouvez définir un temps d'expiration directement dans la commande SET. C'est beaucoup plus efficace que de définir la clé puis d'appeler EXPIRE séparément.

  • EX secondes : Définit le temps d'expiration en secondes.
  • PX millisecondes : Définit le temps d'expiration en millisecondes.
  • EXAT timestamp : Définit l'expiration à un timestamp Unix spécifique (secondes).
  • PXAT timestamp : Définit l'expiration à un timestamp Unix spécifique (millisecondes).

Exemple : définir une clé pour expirer dans une heure :

127.0.0.1:6379> SET cache:product:500 "Product Details" EX 3600
OK

127.0.0.1:6379> TTL cache:product:500 
(integer) 3598 

Utilisez SET key value EX N ou PX N pour les entrées de cache. Cela fait de l'écriture et de l'expiration une seule commande, ce qui évite le bogue courant où l'application écrit une clé de cache et plante avant d'appeler EXPIRE.

Combinaison d'options

Toutes les options peuvent souvent être combinées pour des opérations atomiques complexes :

# Définir la clé uniquement si elle n'existe pas, et la faire expirer dans 60 secondes
SET my_config_setting "active" NX EX 60

2. Récupération de données : La commande GET

La commande GET récupère la valeur de chaîne associée à une clé donnée. C'est l'une des opérations les plus rapides de Redis, souvent effectuée en microsecondes.

Syntaxe de base et utilisation

GET key

Exemple : Récupération du nom d'utilisateur stocké

127.0.0.1:6379> GET user:100:name
"Alice Johnson"

Gestion des clés inexistantes

Si la clé n'existe pas, GET renvoie une réponse spéciale indiquant que rien n'a été trouvé :

127.0.0.1:6379> GET non_existent_key
(nil)

Dans le code de l'application, recevoir (nil) est la manière standard de déterminer que les données sont manquantes, déclenchant généralement un échec de cache où l'application doit récupérer les données de la source principale (comme une base de données) et les réécrire ensuite dans Redis.

Obtenir une valeur tout en modifiant l'expiration : GETEX

La commande de base GET renvoie uniquement la valeur. Elle ne renvoie pas le TTL restant. Si vous avez besoin du TTL, utilisez TTL key ou PTTL key comme commande séparée.

GETEX est différent : il renvoie la valeur et modifie l'expiration de la clé en même temps. C'est utile pour le comportement de session glissante, où chaque lecture prolonge la durée de vie de la session.

GETEX session:abc123 EX 1800

Cela lit la valeur de la session et réinitialise l'expiration à 30 minutes. N'utilisez pas cela à la légère pour les lectures de cache normales, car chaque lecture devient une opération de type écriture qui modifie les métadonnées de la clé.

3. Application pratique : Mise en cache avec GET et SET

Le cas d'utilisation fondamental de GET et SET est l'implémentation d'un modèle simple de cache-aside.

Étapes dans la logique de l'application :

  1. Essayez GET product:500.
  2. Si Redis renvoie une valeur, décodez-la et renvoyez-la.
  3. Si Redis renvoie nil, récupérez le produit de la base de données primaire.
  4. Stockez le résultat sérialisé avec SET product:500 <json> EX 300.
  5. Renvoyez le résultat à l'appelant.

Ce modèle peut réduire la charge de la base de données, mais il crée également une fenêtre de données obsolètes. Si le produit change dans la base de données, Redis peut toujours servir l'ancienne valeur jusqu'à ce que le TTL expire ou que votre application invalide la clé. Choisissez les TTL en fonction de l'erreur autorisée sur les données, pas seulement du trafic que vous souhaitez économiser.

Nommer les clés sans créer de désordre

Redis n'exige pas de convention de nommage, mais votre futur vous-même le fera. Un modèle lisible comme user:100:name, product:500:summary, ou rate:user:100:login rend le débogage avec redis-cli beaucoup plus facile.

Gardez les clés claires et raisonnablement courtes. Économiser quelques octets en nommant une clé u:100:n vaut rarement la confusion, sauf si vous opérez à très grande échelle et avez mesuré la surcharge des clés. Pour la plupart des équipes, la cohérence est plus importante que l'extrême brièveté.

Soyez prudent avec les valeurs fournies par l'utilisateur dans les clés. Si une adresse e-mail, une URL ou un nom de locataire fait partie de la clé, normalisez-la d'abord. Sinon, de petites différences de formatage peuvent créer des entrées de cache en double :

[email protected]
[email protected]
 [email protected]

Celles-ci peuvent toutes représenter le même utilisateur pour votre application mais des clés différentes pour Redis.

Écrasements, valeurs vides et Nil

SET écrase par défaut :

SET config:mode "safe"
SET config:mode "fast"
GET config:mode

La valeur finale est "fast". Si l'écrasement est dangereux, utilisez NX ou XX.

Distinguer également une clé manquante d'une valeur vide. Redis nil signifie que la clé est manquante. Une chaîne vide est une valeur stockée réelle :

SET user:100:nickname ""
GET user:100:nickname

Votre bibliothèque cliente peut représenter ces différences : null, None, nil, une chaîne d'octets vide ou une chaîne vide. Vérifiez le comportement du client au lieu de deviner.

Modèle de verrouillage sûr, avec un avertissement

Vous verrez souvent ce modèle :

SET lock:invoice:123 "worker-7:1700000000" NX EX 30

Cela signifie "créer ce verrou uniquement s'il n'existe pas, et le faire expirer après 30 secondes." L'expiration n'est pas facultative. Sans elle, un travailleur planté peut laisser un verrou pour toujours.

Pour les configurations Redis à instance unique simples, ce modèle est souvent suffisant pour une coordination à faible risque. Pour le verrouillage distribué critique en cas de pannes, de dérive d'horloge et de plusieurs nœuds Redis, utilisez une bibliothèque bien évaluée et comprenez ses compromis. Un bogue de verrouillage peut devenir un bogue de corruption de données.

Débogage avec redis-cli

Lorsqu'un chemin GET ou SET se comporte étrangement, vérifiez la clé directement :

redis-cli GET product:500
redis-cli TTL product:500
redis-cli TYPE product:500

TYPE est utile car GET fonctionne uniquement sur les valeurs de chaîne. Si la clé contient un hachage, une liste, un ensemble ou un ensemble trié, Redis renvoie une erreur de type incorrect. Cela signifie généralement que deux parties de l'application utilisent le même nom de clé à des fins différentes.

Si vous devez inspecter plusieurs clés connexes pendant le développement, SCAN est plus sûr que KEYS sur un serveur de production occupé :

redis-cli SCAN 0 MATCH 'product:500:*' COUNT 100

KEYS * peut bloquer Redis pendant qu'il analyse l'espace de clés. C'est acceptable sur une petite instance locale. C'est une mauvaise habitude en production.

Choisir les TTL dans les systèmes réels

Le choix du TTL est une décision produit et opérationnelle, pas une astuce Redis. Un cache de profil utilisateur peut tolérer cinq minutes d'obsolescence. Une vérification d'autorisation peut nécessiter un TTL beaucoup plus court ou une invalidation explicite. Un indicateur de fonctionnalité peut nécessiter des mises à jour quasi immédiates s'il contrôle un déploiement risqué.

Voici trois modèles courants :

SET cache:product:500 "<json>" EX 300
SET session:abc123 "<json>" EX 1800
SET rate:user:100:login "1" EX 60 NX

Le cache de produit peut être un peu obsolète. La session a une durée de vie claire. La clé de limite de débit utilise NX afin que la première tentative crée la fenêtre et que les tentatives ultérieures puissent incrémenter ou vérifier les clés associées selon la conception.

Évitez les clés de "cache permanent" sauf si vous avez un chemin d'invalidation clair. Un cache permanent devient éventuellement une deuxième base de données, généralement sans la discipline opérationnelle que vous appliquez à la vraie base de données.

Détails de sérialisation

Les chaînes Redis sont binaires-sûres. Elles peuvent contenir du JSON, MessagePack, des données compressées, des compteurs ou du texte brut. La commande ne s'en soucie pas. Votre application, oui.

Le JSON est facile à inspecter :

SET product:500 "{\"id\":500,\"name\":\"Desk Lamp\"}" EX 300

Les formats binaires peuvent économiser de l'espace ou du CPU dans certaines applications, mais ils rendent le débogage en terminal plus difficile. La compression peut aider pour les grandes données répétées, mais elle ajoute également un coût CPU et peut cacher le fait que vous mettez en cache des objets trop volumineux.

Pour les compteurs, ne lisez pas avec GET, n'ajoutez pas dans l'application et n'écrivez pas avec SET si plusieurs clients peuvent mettre à jour la même clé. Utilisez plutôt les commandes de compteur atomique Redis :

INCR page:view:500
EXPIRE page:view:500 86400

Pour les compteurs avec première écriture et expiration, utilisez une transaction ou un petit script Lua si vous avez besoin d'un comportement strict. Sinon, soyez clair sur la condition de concurrence que vous acceptez.

Éviter les collisions de clés

Deux équipes utilisant la même base de données Redis peuvent accidentellement réutiliser une clé comme user:100. Une équipe stocke du JSON avec SET ; une autre stocke des champs avec HSET. Le prochain GET renvoie une erreur de type incorrect, et les deux équipes perdent du temps.

Les espaces de noms aident :

shop:prod:user:100:profile
shop:prod:session:abc123
billing:prod:invoice:9001

Vous n'avez pas besoin de clés douloureusement longues, mais incluez suffisamment de contexte pour éviter les collisions entre environnements, services et types de données. Si vous partagez Redis entre applications, une convention de nommage fait partie de l'interface.

Quand ne pas utiliser GET et SET

Les chaînes sont le point de départ, pas l'ensemble du modèle Redis. Si vous mettez fréquemment à jour un champ dans un blob JSON plus grand, un hachage peut être plus propre :

HSET user:100 name "Alice Johnson" email "[email protected]"
HGET user:100 email

Si vous avez besoin d'événements ordonnés, utilisez des flux ou des listes. Si vous avez besoin de vérifications d'appartenance, utilisez des ensembles. Si vous avez besoin de classement, utilisez des ensembles triés. Réécrire une chaîne sérialisée entière pour chaque petit changement est simple au début, mais cela peut devenir coûteux et maladroit à mesure que l'objet grandit.

Une petite liste de contrôle avant le déploiement

Avant de déployer un nouveau chemin GET et SET, posez quelques questions simples.

  • Quel est le nom exact de la clé ?
  • Deux services peuvent-ils accidentellement utiliser la même clé ?
  • La clé doit-elle expirer ?
  • Que se passe-t-il lorsque Redis renvoie nil ?
  • L'écrasement est-il acceptable, ou l'écriture doit-elle utiliser NX ou XX ?
  • La valeur est-elle suffisamment petite pour être lue et écrite comme une seule chaîne ?
  • Pouvez-vous déboguer la valeur à partir de redis-cli si le comportement en production semble erroné ?

Ces questions attrapent la plupart des erreurs de base de chaînes Redis avant qu'elles ne deviennent des incidents. La syntaxe de la commande est facile. Le cycle de vie autour de la clé est là où les bogues se cachent généralement.

GET et SET sont de petites commandes avec beaucoup de poids opérationnel. Utilisez les expirations pour les données de cache, utilisez NX ou XX lorsque les écrasements comptent, traitez nil comme un état séparé et gardez les noms de clés suffisamment cohérents pour que quelqu'un puisse les déboguer depuis un terminal. Une fois que les chaînes commencent à sembler à l'étroit, déplacez les champs connexes dans des hachages et utilisez la structure de données qui correspond au modèle d'accès.