← Formation BDD

🔴 BD07 — Redis Fondamentaux

Redis 7 Durée : ~2h In-Memory

1. Introduction à Redis

Redis (Remote Dictionary Server) est un store de données en mémoire, ultra-rapide (< 1 ms), utilisé comme cache, broker de messages, gestionnaire de sessions et bien plus.

Cas d'usage

Cas d'usageStructure Redis
Cache de requêtes APIString (JSON sérialisé)
Sessions utilisateurHash
File de tâchesList (LPUSH/BRPOP)
Tags & sets d'utilisateursSet
Leaderboards / classementsSorted Set
Compteurs, rate limitingString (INCR)
Pub/Sub messagerieChannel
Streams temps réelStream (XADD)
npm install ioredis
# ou
npm install redis
const Redis = require('ioredis');
const redis = new Redis({
  host: process.env.REDIS_HOST || '127.0.0.1',
  port: parseInt(process.env.REDIS_PORT || '6379'),
  password: process.env.REDIS_PASSWORD,
  db: 0,
  retryStrategy: (times) => Math.min(times * 50, 2000)
});

2. Strings

Type de base : texte, entiers, binaires. Max 512 Mo.

// SET / GET
await redis.set('user:42:name', 'Alice');
const name = await redis.get('user:42:name');

// SET avec expiration
await redis.set('session:abc', JSON.stringify({ userId: 42 }), 'EX', 3600); // 1h
await redis.setex('token:xyz', 900, 'data'); // 15 min

// Compteurs atomiques
await redis.incr('page:home:views');
await redis.incrby('stats:logins', 1);
await redis.decr('stock:product:1');

// Opérations multiples
await redis.mset('key1', 'val1', 'key2', 'val2');
const vals = await redis.mget('key1', 'key2');

// NX = only if Not eXists
const ok = await redis.set('lock:resource', '1', 'EX', 30, 'NX');
// ok = 'OK' si obtenu, null sinon

3. Lists

Liste doublement chaînée. Idéal pour files de messages, historiques récents.

// LPUSH / RPUSH
await redis.lpush('queue:emails', JSON.stringify({ to: 'alice@test.com', subject: 'Bienvenue' }));
await redis.rpush('history:user:42', 'product:1', 'product:5');

// Pop bloquant (file de workers)
const [list, item] = await redis.blpop('queue:emails', 5); // timeout 5s
if (item) {
  const task = JSON.parse(item);
  await sendEmail(task);
}

// Consultation
const recent = await redis.lrange('history:user:42', 0, 9); // 10 derniers
const length = await redis.llen('queue:emails');

// Garder seulement les N derniers
await redis.ltrim('history:user:42', 0, 49); // garder 50 max

4. Sets

Ensemble non ordonné de membres uniques. Opérations d'ensemble très efficaces.

// Ajouter / retirer
await redis.sadd('tags:post:1', 'javascript', 'redis', 'backend');
await redis.srem('tags:post:1', 'redis');

// Vérifier l'appartenance
const isMember = await redis.sismember('online:users', '42'); // 0 ou 1

// Lister
const members = await redis.smembers('tags:post:1');
const count = await redis.scard('online:users');

// Opérations d'ensemble
const common = await redis.sinter('friends:alice', 'friends:bob');    // intersection
const all    = await redis.sunion('online:FR', 'online:BE');          // union
const diff   = await redis.sdiff('subscribers:plan:pro', 'paid');     // différence

// Déplacer un membre
await redis.smove('online:users', 'away:users', '42');

5. Hashes

Dictionnaire clé-valeur. Parfait pour stocker les attributs d'un objet.

// HSET / HGET
await redis.hset('user:42', {
  name: 'Alice Dupont',
  email: 'alice@example.com',
  role: 'admin',
  loginCount: '0'
});

const email = await redis.hget('user:42', 'email');
const user  = await redis.hgetall('user:42'); // objet complet

// Incrémenter un champ
await redis.hincrby('user:42', 'loginCount', 1);

// Vérifier / supprimer un champ
const exists = await redis.hexists('user:42', 'phone');
await redis.hdel('user:42', 'tempToken');

// Lister les champs
const keys   = await redis.hkeys('user:42');
const values = await redis.hvals('user:42');
const len    = await redis.hlen('user:42');

6. Sorted Sets (ZSets)

Ensemble avec score flottant. Membres triés par score. Idéal pour leaderboards.

// ZADD
await redis.zadd('leaderboard:game', 1500, 'alice', 2300, 'bob', 900, 'charlie');

// Classement (du plus grand score)
const top10 = await redis.zrevrange('leaderboard:game', 0, 9, 'WITHSCORES');

// Rang d'un joueur (0-based)
const rank  = await redis.zrevrank('leaderboard:game', 'alice');
const score = await redis.zscore('leaderboard:game', 'alice');

// Incrémenter le score
await redis.zincrby('leaderboard:game', 50, 'alice');

// Plage de scores
const midRange = await redis.zrangebyscore('leaderboard:game', 1000, 2000);

// Supprimer
await redis.zrem('leaderboard:game', 'charlie');
const count = await redis.zcard('leaderboard:game');

7. TTL & Expiration

// Définir un TTL
await redis.expire('cache:users', 300);        // 5 min (secondes)
await redis.pexpire('rate:ip:1.2.3.4', 60000); // 60s (ms)

// Vérifier le TTL restant
const ttl  = await redis.ttl('session:abc');   // secondes (-2 = n'existe pas)
const pttl = await redis.pttl('session:abc');  // millisecondes

// Supprimer le TTL (rendre persistant)
await redis.persist('important:key');

// Supprimer une clé
await redis.del('temp:data');
await redis.del('key1', 'key2', 'key3'); // multiple

// Vérifier l'existence
const exists = await redis.exists('user:42'); // 1 ou 0

// Pattern scan (préférer SCAN à KEYS en prod)
const [cursor, keys] = await redis.scan(0, 'MATCH', 'user:*', 'COUNT', 100);