1 / 20

Structures de Données Avancées

Partie 2 - Au-delà du simple cache

Lists, Sets, Sorted Sets, Hashes et Streams
Les super-pouvoirs de Redis

2 / 20

Objectifs de cette partie

  • Maîtriser toutes les structures de données Redis
  • Comprendre les cas d'usage de chaque structure
  • Connaître la complexité des opérations
  • Implémenter des solutions réelles : ranking, timeline, panier
  • Découvrir Redis Streams pour l'event sourcing
3 / 20

Les structures de données Redis

📝 Strings

Valeurs simples + opérations atomiques

Compteurs, cache, sessions

📋 Lists

Listes doublement chaînées

Queues, timelines, logs

🎯 Sets

Collections non ordonnées uniques

Tags, relations, unique visitors

🏆 Sorted Sets

Sets ordonnés par score

Leaderboards, indices, ranges

🗂️ Hashes

Maps field-value

Objets, profils, configurations

🌊 Streams

Log append-only

Events, IoT, chat, logs

4 / 20

Strings : Opérations avancées

# Opérations atomiques sur les nombres
INCR stats:page:home:views
(integer) 1234

INCRBY product:1001:stock -5
(integer) 45

# Opérations sur les chaînes
APPEND log:events "\n2024-01-15: User login"
(integer) 156

# Get et Set atomique
GETSET config:version "2.0"
"1.9"

# Opérations bit-à-bit
SETBIT user:1001:features 5 1
GETBIT user:1001:features 5
5 / 20

Pattern : Compteurs distribués

# Compteur simple
INCR api:calls:total

# Compteur avec expiration (rate limiting)
SET api:user:1001:calls:2024-01-15-14 0 EX 3600
INCR api:user:1001:calls:2024-01-15-14

# Vérifier la limite
GET api:user:1001:calls:2024-01-15-14
"42"

Cas d'usage : Analytics, Rate limiting, Statistiques temps réel

6 / 20

Lists : Listes doublement chaînées

HEAD ← → [A] ← → [B] ← → [C] ← → TAIL
# Ajout d'éléments
LPUSH timeline:user:1001 "Post 3"
LPUSH timeline:user:1001 "Post 4"
RPUSH timeline:user:1001 "Post 1"

# Récupération
LRANGE timeline:user:1001 0 -1
1) "Post 4"
2) "Post 3"
3) "Post 1"

# Limiter la taille
LTRIM timeline:user:1001 0 99
7 / 20

Patterns avec Lists

📨 Queue (FIFO)

LPUSH queue:emails "email1"
RPOP queue:emails

📚 Stack (LIFO)

LPUSH stack:tasks "task1"
LPOP stack:tasks

📰 Timeline sociale

LPUSH feed:user:id "post"
LRANGE feed:user:id 0 20
Opération Complexité Description
LPUSH/RPUSH O(1) Ajout en tête/queue
LPOP/RPOP O(1) Retrait en tête/queue
LRANGE O(N) Récupération d'une plage
8 / 20

Sets : Collections non ordonnées

# Gestion des tags d'un article
SADD article:1001:tags "redis" "database" "nosql"
(integer) 3

# Vérifier l'appartenance
SISMEMBER article:1001:tags "redis"
(integer) 1

# Tous les membres
SMEMBERS article:1001:tags
1) "database"
2) "nosql"
3) "redis"

# Nombre d'éléments
SCARD article:1001:tags
(integer) 3
9 / 20

Sets : Opérations ensemblistes

# Followers de deux utilisateurs
SADD followers:fatima "ahmed" "sara" "youssef"
SADD followers:hassan "sara" "youssef" "laila"

# Intersection - Followers communs
SINTER followers:fatima followers:hassan
1) "sara"
2) "youssef"

# Union - Tous les followers
SUNION followers:fatima followers:hassan
1) "ahmed" 2) "sara" 3) "youssef" 4) "laila"

# Différence - Followers exclusifs à Fatima
SDIFF followers:fatima followers:hassan
1) "ahmed"
10 / 20

Patterns avec Sets

👥 Relations sociales

Amis, followers, likes

SADD friends:user:1001 "user:1002"

🏷️ Système de tags

Articles, produits, posts

SADD tag:redis "article:1" "article:2"

👁️ Visiteurs uniques

Analytics sans doublons

SADD visitors:2024-01-15 "ip:192.168.1.1"
# Exemple : Recommandations d'amis
# Amis d'amis qui ne sont pas déjà mes amis
SUNION friends:ahmed:friends friends:sara:friends
SDIFF temp:recommendations friends:youssef
11 / 20

Sorted Sets : L'arme secrète de Redis

# Leaderboard de jeu
ZADD leaderboard:game:tetris 3500 "Ahmed"
ZADD leaderboard:game:tetris 4200 "Fatima"
ZADD leaderboard:game:tetris 3800 "Hassan"

# Top 3 (ordre décroissant)
ZREVRANGE leaderboard:game:tetris 0 2 WITHSCORES
1) "Fatima"
2) "4200"
3) "Hassan"
4) "3800"
5) "Ahmed"
6) "3500"

# Rang d'un joueur
ZREVRANK leaderboard:game:tetris "Hassan"
(integer) 1 # 2ème position (0-indexed)
12 / 20

Sorted Sets : Cas d'usage avancés

# 1. Trending topics (score = timestamp)
ZADD trending:morocco 1705334400 "#CAN2024"
ZADD trending:morocco 1705338000 "#AtlasLions"

# 2. Géolocalisation (score = géohash)
ZADD stores:location 33.5731 "Store:Casablanca"
ZADD stores:location 34.0209 "Store:Rabat"

# 3. Priority queue (score = priorité)
ZADD tasks:queue 1 "send-email"
ZADD tasks:queue 10 "backup-db"
ZADD tasks:queue 5 "generate-report"

# Récupérer par priorité
ZPOPMAX tasks:queue
"backup-db"
13 / 20

Hashes : Objets structurés

# Profil utilisateur
HSET user:1001 name "Fatima Zahra"
HSET user:1001 email "fz@example.ma"
HSET user:1001 city "Casablanca"

# Ou en une seule commande
HMSET product:3456 name "Huile d'Argan Bio" price "250" stock "45" category "Cosmétique"

# Récupération
HGET user:1001 name
"Fatima Zahra"

HGETALL user:1001
1) "name"
2) "Fatima Zahra"
3) "email"
4) "fz@example.ma"
5) "city"
6) "Casablanca"
14 / 20

Hashes vs String JSON

Aspect Hash String JSON
Accès partiel ✅ HGET field spécifique ❌ GET tout + parse
Mise à jour partielle ✅ HSET un seul field ❌ GET + modify + SET
Utilisation mémoire ✅ Optimisé pour petits objets ➖ Plus compact pour gros objets
Atomicité ✅ HINCRBY atomique ❌ Pas d'opération atomique
Nested objects ❌ Un seul niveau ✅ Structures complexes
# Incrément atomique avec Hash
HINCRBY product:3456 views 1
HINCRBY product:3456 stock -1
15 / 20

Streams : Le log append-only

# Ajouter des événements
XADD events:orders * order_id 1001 user_id 2001 amount 250 status "confirmed"
"1705334567890-0"

# Lire depuis le début
XRANGE events:orders - +

# Consumer groups
XGROUP CREATE events:orders analytics-group $
XREADGROUP GROUP analytics-group consumer1 COUNT 10 STREAMS events:orders >

Avantages : Ordre garanti, Consumer groups, Acknowledgment, Replay possible

16 / 20

Streams : Cas d'usage

📊 Event Sourcing

Historique complet des changements

Audit trail, CQRS

🌡️ IoT / Sensors

Flux de données temps réel

Température, GPS, métriques

💬 Chat / Messaging

Messages ordonnés avec historique

WhatsApp-like, notifications

📝 Activity Logs

Logs applicatifs centralisés

User actions, système events

# Exemple : IoT sensor data
XADD sensor:temp:room1 * temp 23.5 humidity 45
XADD sensor:temp:room1 MAXLEN ~ 1000 * temp 23.8 humidity 44
17 / 20

Quelle structure choisir ?

Besoin Structure Exemple
Valeur simple, compteurs String Cache, sessions, counters
File d'attente, timeline List Queue jobs, feed social
Unicité, appartenance Set Tags, followers, online users
Classement, ordre Sorted Set Leaderboard, index, priority queue
Objet avec fields Hash User profile, config, product
Log ordonné, event stream Stream Events, chat, IoT data
18 / 20

Complexité des opérations

Structure Ajout Accès Suppression Recherche
String O(1) O(1) O(1) -
List (head/tail) O(1) O(N) O(1) O(N)
Set O(1) O(1) O(1) O(1)
Sorted Set O(log N) O(log N) O(log N) O(log N)
Hash O(1) O(1) O(1) O(N)
Stream O(1) O(N) O(N) O(N)

💡 Redis reste ultra-rapide même avec O(N) grâce à l'in-memory

19 / 20

Exemple : E-commerce marocain

# 1. Panier utilisateur (Hash)
HSET cart:user:1001 product:3456 2
HSET cart:user:1001 product:3457 1

# 2. Produits populaires (Sorted Set)
ZINCRBY products:popular 1 "Huile d'Argan"
ZREVRANGE products:popular 0 9

# 3. Utilisateurs en ligne (Set)
SADD users:online "user:1001"
EXPIRE users:online 300

# 4. Historique commandes (Stream)
XADD orders:stream * user 1001 total 750 items 3

# 5. Queue de traitement (List)
LPUSH orders:pending "order:5678"
20 / 20

Points clés à retenir

  • Strings : Plus que du texte - compteurs atomiques, bitmaps
  • Lists : Parfaites pour queues et timelines
  • Sets : Relations et unicité garantie
  • Sorted Sets : La star pour classements et indices
  • Hashes : Objets légers avec accès aux fields
  • Streams : Event sourcing et messaging moderne

🚀 Prochaine partie : Intégration avec Node.js

Transformez ces structures en applications puissantes !