Salta ai contenuti

Scale · 06 · Capstone

Esercizio conclusivo senza comandi pronti: qui costruisci tu, con quello che hai usato nelle cinque unità precedenti.


Ti viene chiesto di mettere in esercizio Redis come cache di sessione per un applicativo con questi vincoli:

  • 40 GB di dataset stimato a regime, chiavi con TTL di 30 minuti
  • 12 istanze applicative, ciascuna con pool da 50 connessioni
  • picco a 120.000 ops/s, letture 80% / scritture 20%
  • RTO 60 secondi, RPO 5 minuti
  • tre nodi fisici in due sale, storage locale NVMe
  • finestra di patching mensile senza interruzione di servizio

Decidi e motiva per iscritto:

  1. Standalone + Sentinel, oppure Cluster? Il discriminante è il dataset da 40 GB, non le ops/s: quale limite tocchi per primo?
  2. maxmemory per istanza e policy di eviction. Ricorda il margine per il fork.
  3. Persistenza: RDB, AOF, entrambi, nessuna? Con RPO 5 minuti, cosa è effettivamente necessario?
  4. Connessioni totali attese: verifica contro maxclients e contro LimitNOFILE. Quanto margine lasci?
  5. Distribuzione dei nodi sulle due sale: dove finiscono i Sentinel (o le replica cluster) perché il quorum sopravviva alla perdita di una sala?

Costruisci la topologia scelta in locale, con i comandi delle unità 03 o 04. Requisiti:

  • avvio scriptato e idempotente (rieseguirlo non deve rompere nulla)
  • attese condizionate, mai sleep fissi
  • verifica finale automatica che fallisca con exit code ≠ 0 se lo stato non è quello atteso

Traccia dello script di verifica:

#!/usr/bin/env bash
set -euo pipefail
fail() { echo "KO: $1" >&2; exit 1; }
[ "$(redis-cli -p 6379 PING)" = "PONG" ] || fail "master non risponde"
# ... aggiungi: ruoli, master_link_status, quorum, cluster_state,
# rdb_last_bgsave_status, maxmemory impostato, rejected_connections = 0
echo "OK"

Prima di rompere, metti sotto carico applicativo la topologia che hai costruito, usando i profili dell’unità 07:

Terminal window
python3 labs/app/workload.py sessions --host <master> --ops 50000 --keyspace 200000
python3 labs/app/workload.py roundtrip --host <master> --ops 20000

Registra baseline di ops/s, hit ratio, used_memory_peak e slowlog. Sono i numeri contro cui misurerai il degrado durante i guasti.


Esegui questi guasti e cronometra il recupero:

GuastoComeCosa misuri
Master uccisokill -9tempo fino al nuovo master servente
Rete della replicaCLIENT KILL TYPE replica sul masterpartial o full sync?
Disco pienoriempi la dir di lavorocosa fa BGSAVE, cosa risponde il master
Saturazione connessionimaxclients basso + client in loopquale contatore lo rivela per primo
Comando lentoDEBUG SLEEPlo slowlog lo cattura con la tua soglia?

Per ognuno registra: cosa hai visto per primo (log, metrica o errore applicativo), tempo di rilevamento, tempo di recupero.


Produci tre artefatti, quelli che servono davvero al passaggio in esercizio:

a) Runbook di primo livello — la catena diagnostica in otto passi dell’unità 05, adattata alla tua topologia, con le soglie decise da te.

b) Procedura di patching senza downtime — sequenza esatta di comandi per aggiornare tutti i nodi rispettando il vincolo di continuità. Punto chiave: si patcha sempre prima la replica, si promuove in modo coordinato, si patcha l’ex master.

c) Tabella delle allerte — metrica, soglia, severità, azione. Massimo dieci righe: se ne servono di più, non hai deciso cosa conta.


Il lavoro è completo quando sai rispondere senza consultare la documentazione:

  • Perché hai scelto quella topologia e a quale soglia cambieresti idea
  • Quanta memoria hai lasciato al fork e perché quella cifra
  • Quanti dati perdi nel caso peggiore, misurato non stimato
  • Chi si accorge per primo di un failover: il monitoraggio o l’utente
  • Cosa succede se cade la sala con la maggioranza del quorum
  • Quale comando esegui per primo quando arriva la segnalazione