Redis: une base de données cache en mémoire pour applications performantes

Redis est une base de données cache non relationnelle (NoSQL) développée en C, conçue pour le stockage en mémoire, offrant une vitesse d'accès élevée. Ses performances s'expliquent par une opération purement en mémoire, un modèle réseau basé sur l'I/O multiplexing, et une architecture mono-processus et mono-thread qui élimine les surcharges de commutation.

La version stable actuelle est la 5.x, tandis que la 7.x est la plus récente. L'installation varie selon le système d'exploitation : sous macOS ou Linux, une compilation à partir du code source est requise, tandis que sous Windows, des binaires précompilés sont disponibles via les dépôts GitHub officiels.

Lors de l'installation sur Windows, deux commandes clés sont fournies :

  • redis-server pour démarrer le serveur, avec des options comme -bind ou -b pour lier une adresse IP, et -port ou -p pour spécifier le port.
  • redis-cli pour lancer le client, qui se connecte par défaut au port local 6379, avec les options -h et -p pour personnaliser la connexion.

Pour les projets Python, l'installation via pip est simple :

pip install redis

Connexion à Redis

Connexion directe

Une connexion directe peut être établie avec les paramètres par défaut ou persnonalisés. Dans un contexte d'application web, chaque requête peut ouvrir une connexion, ce qui risque de surcharger le serveur avec de multiples connexions simultanées.

import redis
client = redis.Redis()  # Connexion locale au port 6379 par défaut
# Pour une connexion personnalisée :
# client = redis.Redis(host='192.168.1.100', port=6380)

def effectuer_tache():
    instance = redis.Redis()
    print(instance.get('clé_utilisateur'))

# Simulation de requêtes concurrentes avec des threads
import threading
for idx in range(100):
    thread = threading.Thread(target=effectuer_tache)
    thread.start()  # Risque de dépassement de connexions sans pooling

Connexion via pool de connexions

Pour limiter le nombre de connexions, un pool de connexions est utilisé, similaire aux concepts de pool de threads ou de processus. Une instance unique du pool est créée pour toute l'application.

## fichier: pool_connexion.py
import redis
POOL_CONNEXION = redis.ConnectionPool(max_connections=50, host='192.168.1.100', port=6380)

Pour utiliser le pool dans le code :

from pool_connexion import POOL_CONNEXION
client_redis = redis.Redis(connection_pool=POOL_CONNEXION)

Types de données dans Redis

Chaînes de caractères

Les chaînes sont le type de base, avec des opérations courantes comme le stockage, la récupération, l'incrémentation et la définition de délais d'expiration.

import redis
c = redis.Redis()
c.set("nom_utilisateur", "alice")
valeur = c.get("nom_utilisateur")  # Retourne b'alice'

c.set("compteur", "10", ex=300)  # Expiration après 300 secondes
c.incrby("compteur", 5)  # Incrémente de 5

c.mset({"clé1": "valeur1", "clé2": "valeur2"})
resultats = c.mget("clé1", "clé2")  # Retourne une liste de valeurs

Voici une table des commandes et leurs équivalents Python :

Commande Redis Méthode Python
SET clé valeur set(clé, valeur)
GET clé get(clé)
APPEND clé valeur append(clé, valeur)
INCRBY clé incrément incrby(clé, incrément)

Listes

Les listes permettent des opérations de type file ou pile, avec des fonctionnalités de blocage pour les files d'attente.

import redis
r = redis.Redis()
r.lpush('file_attente', 'tâche_a')
r.lpush('file_attente', 'tâche_b', 'tâche_c')
premier = r.lpop('file_attente')  # Retire et retourne b'tâche_c'
longueur = r.llen('file_attente')  # Nombre d'éléments

# Opération bloquante avec délai
element = r.blpop('file_attente', timeout=10)  # Bloque jusqu'à 10 secondes

Hash

Les hash stockent des paires clé-valeur, idéales pour les objets structurés.

h = redis.Redis()
h.hset('profil:1', 'nom', 'bob')
h.hset('profil:1', 'age', '30')
donnees = h.hgetall('profil:1')  # Retourne un dictionnaire de bytes

Ensembles

Les ensembles gèrent des collections non ordonnées d'éléments uniques, avec des opérations d'intersection, d'union et de différence.

ens = redis.Redis()
ens.sadd('tags', 'python', 'redis')
membres = ens.smembers('tags')  # Retourne tous les membres

Ensembles triés

Les ensembles triés associent un score à chaque membre, permettant des requêtes ordonnées.

tri = redis.Redis()
tri.zadd('classement', {'alice': 95, 'bob': 87})
tri_par_score = tri.zrangebyscore('classement', 80, 100)

Méthodes communes

Certaines méthodes s'appliquent à tous les types de données :

Méthode Description
delete(*clés) Supprime les clés spécifiées
exists(clé) Vérifie l'existence d'une clé
keys(pattern) Retourne les clés correspondant au modèle
expire(clé, temps) Définit une durée d'expiration

Pipelines dans Redis

Les pipelines permettent d'exécuter plusieurs commandes en une seule transaction, réduisant les allers-retours réseau.

import redis
client = redis.Redis()
pipeline = client.pipeline(transaction=True)
pipeline.multi()  # Début de la transaction
pipeline.incr('solde_compte_a')
pipeline.decr('solde_compte_b')
resultats = pipeline.execute()  # Exécution atomique

Intégration dans Django

Configuration personnalisée

Pour une utilisation générique, un pool de connexions peut être configuré indépendamment de Django.

## fichier: config_redis.py
import redis
POOL_GLOBAL = redis.ConnectionPool(max_connections=200)

def obtenir_connexion():
    return redis.Redis(connection_pool=POOL_GLOBAL)

Configuration du cache Django avec Redis

Django offre un système de cache intégré qui peut être configuré pour utiliser Redis comme backend, avec sérialisation automatique via pickle.

## Dans settings.py
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://localhost:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 150}
        }
    }
}

Utilisation du module django-redis

Avec le paquet django-redis installé, une connexion directe au pool configuré peut être obtenue.

from django_redis import get_redis_connection
connexion = get_redis_connection("default")
connexion.set('cle_cache', 'valeur')
valeur_cachee = connexion.get('cle_cache')

Étiquettes: Redis Python Django Cache NoSQL

Publié le 1 juin à 20h35