Blog

Introduzione a Redis

2026-06-09

Un' introduzione pratica al database Redis per applicazioni locali

  • Database
  • Redis
  • Programmazione

Redis: il database che vive in memoria

Categoria: Database | Livello: Principiante–Intermedio


Cos'è Redis?

Redis (acronimo di REmote DIctionary Server) è un database in-memory open source, nato nel 2009 per mano di Salvatore Sanfilippo. A differenza dei database relazionali che scrivono i dati su disco, Redis li mantiene direttamente in RAM, raggiungendo velocità di accesso dell'ordine dei microsecondi.

Non è un semplice database chiave-valore: Redis supporta strutture dati evolute come liste, insiemi, hash e code con priorità, rendendolo uno strumento estremamente versatile.

> 💡 Curiosità: Redis è usato da Twitter, GitHub, Stack Overflow, Snapchat e da milioni di applicazioni in tutto il mondo come strato di caching e gestione delle sessioni.


Architettura: in-memory vs on-disk

Il punto distintivo di Redis è dove risiedono i dati durante l'esecuzione.

Caratteristica Database tradizionale (es. MySQL) Redis
Dove vivono i dati Disco (HDD/SSD) RAM (memoria principale)
Velocità di accesso Millisecondi Microsecondi
Modello dei dati Tabelle relazionali Strutture dati (key-value++)
Persistenza Sempre su disco Opzionale (RDB o AOF)
Capacità tipica Terabyte Limitata dalla RAM disponibile
Query language SQL Comandi specifici per tipo
Uso principale Dati applicativi permanenti Cache, sessioni, code, pub/sub

Il fatto di lavorare in RAM è sia il punto di forza che il limite principale: i dati sono fulminei da leggere e scrivere, ma la capacità è vincolata dalla memoria fisica del server.


Quando usare Redis

Redis non sostituisce un database relazionale, ma lo affianca per risolvere problemi specifici con efficienza.

✅ Redis è la scelta giusta quando:

  • Hai bisogno di una cache per ridurre i tempi di risposta (es. query costose salvate temporaneamente)
  • Vuoi gestire le sessioni utente in modo veloce e scalabile
  • Devi implementare una coda di messaggi o un sistema di task in background
  • Vuoi un sistema di rate limiting (es. massimo 100 richieste al minuto per utente)
  • Hai bisogno di leaderboard in tempo reale (es. classifiche di un gioco)
  • Vuoi implementare un sistema pub/sub per messaggi in tempo reale
  • Hai dati con scadenza automatica (es. token temporanei, OTP, link di verifica)

❌ Redis non è adatto quando:

  • I tuoi dati devono persistere in modo affidabile senza configurazioni aggiuntive
  • Hai dataset di dimensioni superiori alla RAM disponibile
  • Hai bisogno di query complesse con JOIN, aggregazioni e transazioni ACID complete
  • Il tuo budget non consente server con tanta memoria RAM

Installazione e primi passi

Su Linux / Ubuntu

sudo apt update
sudo apt install redis-server

# Avvio del servizio
sudo systemctl start redis-server
sudo systemctl enable redis-server

# Verifica
redis-cli ping
# Output: PONG

Su Windows

Il modo più semplice è usare WSL2 (Windows Subsystem for Linux) oppure Docker:

docker run -d -p 6379:6379 --name redis redis:latest

Connessione alla shell interattiva

redis-cli

Il prompt cambia in 127.0.0.1:6379> — sei connesso al server Redis locale sulla porta predefinita 6379.


Il modello chiave-valore

La base di Redis è semplice: ogni dato è identificato da una chiave (stringa) e ha un valore associato. La chiave è univoca all'interno del database.

# Imposta un valore
SET nome "Mario Rossi"

# Leggi il valore
GET nome
# Output: "Mario Rossi"

# Cancella una chiave
DEL nome

# Verifica se una chiave esiste
EXISTS nome
# Output: 0 (non esiste) oppure 1 (esiste)

# Conta tutte le chiavi presenti
DBSIZE

Scadenza automatica (TTL)

Una delle funzionalità più potenti di Redis è la possibilità di impostare una scadenza su qualsiasi chiave:

# Imposta un valore con scadenza di 60 secondi
SET token:abc123 "utente_42" EX 60

# Controlla il tempo rimanente
TTL token:abc123
# Output: 58 (secondi rimanenti)

# Dopo la scadenza
TTL token:abc123
# Output: -2 (la chiave non esiste più)

Questo meccanismo è perfetto per token di sessione, OTP e dati temporanei.


Le strutture dati principali

Redis non è un semplice dizionario: supporta diversi tipi di valore, ognuno con i propri comandi ottimizzati.

1. String — il tipo base

Il tipo più semplice: una chiave associata a una stringa (o numero).

SET contatore 0
INCR contatore      # → 1
INCR contatore      # → 2
INCRBY contatore 5  # → 7
DECR contatore      # → 6

INCR è atomico: anche con più client che operano contemporaneamente, non ci sono race condition. Perfetto per contatori di visite o like.

2. List — lista ordinata

Una lista di stringhe, accessibile da entrambi gli estremi come una deque.

RPUSH coda:lavori "job_1"   # Aggiunge in coda
RPUSH coda:lavori "job_2"
RPUSH coda:lavori "job_3"

LRANGE coda:lavori 0 -1     # Legge tutta la lista
# Output: job_1, job_2, job_3

LPOP coda:lavori            # Estrae dal fronte (FIFO)
# Output: "job_1"

Caso d'uso tipico: code di task per sistemi di elaborazione asincrona.

3. Hash — dizionario annidato

Un hash associa a una chiave un insieme di coppie campo-valore. Ideale per rappresentare oggetti.

HSET studente:42 nome "Giulia" cognome "Ferrari" classe "4A" media 8.2

HGET studente:42 nome          # → "Giulia"
HGETALL studente:42            # → tutti i campi e valori
HINCRBY studente:42 media 0.3  # Incrementa il campo numerico

4. Set — insieme senza duplicati

Un insieme non ordinato di stringhe uniche.

SADD tag:articolo "database" "nosql" "redis" "cache"
SADD tag:articolo "redis"    # Non aggiunge: già presente

SMEMBERS tag:articolo        # Elenca tutti i tag
SISMEMBER tag:articolo "sql" # → 0 (non presente)
SCARD tag:articolo           # → 4 (numero di elementi)

5. Sorted Set — classifica con punteggio

Come un Set, ma ogni elemento ha un punteggio numerico che determina l'ordinamento. Perfetto per le classifiche.

ZADD classifica 1500 "mario"
ZADD classifica 2300 "giulia"
ZADD classifica 1800 "luca"

# Top 3 in ordine decrescente
ZREVRANGE classifica 0 2 WITHSCORES
# Output: giulia 2300, luca 1800, mario 1500

# Aggiorna il punteggio
ZINCRBY classifica 200 "mario"

Redis in Python: esempio pratico

Installa la libreria client:

pip install redis

Esempio 1 — Cache di query costosa

import redis
import time

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

def get_dati_studente(id_studente):
    cache_key = f"studente:{id_studente}"

    # Controlla la cache
    cached = r.get(cache_key)
    if cached:
        print("✅ Dati dalla cache")
        return cached

    # Simula una query lenta al database
    print("⏳ Query al database...")
    time.sleep(2)
    dati = f"Studente {id_studente}: Giulia Ferrari, 4A, media 8.2"

    # Salva in cache per 30 secondi
    r.set(cache_key, dati, ex=30)
    return dati

# Prima chiamata: query al database
print(get_dati_studente(42))

# Seconda chiamata: risposta immediata dalla cache
print(get_dati_studente(42))

Esempio 2 — Contatore di visite con rate limiting

import redis

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

def registra_visita(pagina: str, ip_utente: str) -> dict:
    # Contatore globale di visite
    visite_totali = r.incr(f"visite:{pagina}")

    # Rate limiting: max 5 richieste al minuto per IP
    rate_key = f"rate:{ip_utente}:{pagina}"
    richieste = r.incr(rate_key)

    if richieste == 1:
        r.expire(rate_key, 60)  # Scadenza di 60 secondi

    bloccato = richieste > 5

    return {
        "visite_totali": visite_totali,
        "richieste_ultimo_minuto": richieste,
        "accesso_consentito": not bloccato
    }

# Simulazione
for i in range(7):
    risultato = registra_visita("home", "192.168.1.1")
    stato = "✅" if risultato["accesso_consentito"] else "🚫 BLOCCATO"
    print(f"Richiesta {i+1}: {stato} | "
          f"Richieste nell'ultimo minuto: {risultato['richieste_ultimo_minuto']}")

Output:

Richiesta 1: ✅ | Richieste nell'ultimo minuto: 1
Richiesta 2: ✅ | Richieste nell'ultimo minuto: 2
Richiesta 3: ✅ | Richieste nell'ultimo minuto: 3
Richiesta 4: ✅ | Richieste nell'ultimo minuto: 4
Richiesta 5: ✅ | Richieste nell'ultimo minuto: 5
Richiesta 6: 🚫 BLOCCATO | Richieste nell'ultimo minuto: 6
Richiesta 7: 🚫 BLOCCATO | Richieste nell'ultimo minuto: 7

Persistenza: Redis non è solo volatile

Per default Redis salva i dati in RAM, ma offre due meccanismi di persistenza opzionali:

RDB (Redis Database Backup)

Crea snapshot periodici del database su disco. Veloce al riavvio, ma si possono perdere gli ultimi dati scritti prima dello snapshot.

# In redis.conf
save 900 1    # Salva se almeno 1 chiave è cambiata negli ultimi 900 secondi
save 300 10   # Salva se almeno 10 chiavi sono cambiate negli ultimi 300 secondi

AOF (Append Only File)

Registra ogni operazione di scrittura su un file di log. Più sicuro, ma più lento di RDB.

# In redis.conf
appendonly yes
appendfsync everysec   # Sincronizza su disco ogni secondo

> 💡 Configurazione consigliata: Per la maggior parte dei casi d'uso, è sufficiente RDB. Per applicazioni critiche, si usano entrambi.


Redis vs SQLite: quando scegliere quale

Scenario SQLite Redis
Dati strutturati e persistenti
Query complesse con relazioni
Cache temporanea ad alta velocità
Sessioni utente con scadenza
Contatori e statistiche in tempo reale
Classifiche e leaderboard
Progetto didattico semplice

Non sono in competizione: spesso si usano insieme. SQLite (o MySQL) per i dati permanenti, Redis per accelerare gli accessi frequenti.


Esercizi proposti

Esercizio 1 — Base Apri redis-cli e crea le seguenti strutture: una stringa con il tuo nome e TTL di 10 secondi; una lista con i giorni della settimana; un hash che rappresenta un prodotto (nome, prezzo, disponibilità). Verifica ogni struttura con i comandi di lettura appropriati.

Esercizio 2 — Intermedio Scrivi un programma Python che simuli un sistema di voti per un sondaggio. Gli utenti (identificati da un ID) possono votare una delle tre opzioni (A, B, C). Usa un Sorted Set per tenere il punteggio in tempo reale e mostra la classifica aggiornata dopo ogni voto. Impedisci che lo stesso utente voti due volte usando un Set.

Esercizio 3 — Avanzato Implementa un sistema di cache con invalidazione: un programma che simula chiamate a un'API esterna (con un time.sleep per simulare la latenza). Le risposte vengono salvate in Redis con TTL di 30 secondi. Quando i dati vengono aggiornati, la cache deve essere invalidata esplicitamente. Misura e mostra il tempo di risposta con e senza cache.


Riepilogo

Concetto Punti chiave
Architettura In-memory, accesso in microsecondi
Strutture dati String, List, Hash, Set, Sorted Set
TTL Scadenza automatica delle chiavi, ideale per dati temporanei
Persistenza Opzionale: RDB (snapshot) o AOF (log continuo)
Quando usarlo Cache, sessioni, code, rate limiting, leaderboard, pub/sub
Quando non usarlo Dati strutturati complessi, dataset superiori alla RAM disponibile
Integrazione Python Libreria redis (pip install redis)

Risorse per approfondire


Articolo pubblicato su filippobilardo.it — Tutti i diritti riservati