Ciao, e benvenuto nell'ottava puntata della settantunesima stagione. Fin qui abbiamo studiato i mostri: la rete bugiarda, i guasti ambigui, le scelte impossibili. Oggi cambiamo registro e diventiamo pratici. Perché tutta questa teoria si trasforma in una manciata di schemi concreti che incontri ogni volta che un sistema deve reggere tanti utenti. Oggi vediamo come si scala davvero, e come questi problemi si presentano nel codice che scrivi tu.
Partiamo dall'idea madre di tutta la scala, che è di una semplicità disarmante: dividere. Se un compito è troppo grosso per una macchina, lo spezzi in pezzi e dai un pezzo a ciascuna. Hai un archivio di dati enorme? Non lo metti tutto su una macchina: lo tagli in fette, e ogni macchina custodisce una fetta. I clienti con cognome dalla A alla L a una filiale, dalla M alla Z a un'altra. Così sai subito a quale macchina mandare ogni richiesta, e ognuna ha solo la sua parte da gestire. Aggiungi utenti? Aggiungi macchine e tagli fette più piccole. Questa divisione dei dati è il primo, grande strumento della scala.
Vediamo il secondo schema, per gestire non i dati ma il traffico: distribuire il carico. Immagina uno sportello unico dove tutti fanno la fila: si intasa subito. La soluzione è avere tanti sportelli identici e un vigile all'ingresso che manda ogni persona a quello più libero. Nei sistemi, quel vigile smista le richieste tra tante macchine gemelle, tutte capaci di fare la stessa cosa. E c'è un trucco importante: quelle macchine devono essere intercambiabili, cioè non tenersi in pancia niente di personale sul singolo cliente. Se ogni sportello è uguale all'altro e non ricorda nulla, puoi spostare le persone liberamente, e se uno sportello chiude nessuno perde il suo posto in coda. La sostituibilità è ciò che rende la distribuzione del carico semplice e robusta.
E qui torna un vecchio amico di tante stagioni, la copia dei dati vicino a chi li usa. Se la stessa informazione viene letta molto più spesso di quanto venga scritta, tenerne copie pronte accanto a chi legge, invece di andarla a prendere ogni volta lontano, fa volare tutto. È l'idea del caching che conosciamo, portata su scala distribuita: tante copie di lettura sparse dove servono. Certo, ci riporta dritti al problema di prima, le copie che divergono, ma spesso, per i dati che si leggono tanto e cambiano poco, un piccolo ritardo di aggiornamento è un prezzo che paghi volentieri in cambio della velocità.
Nota ora uno schema che nasce direttamente dalla rete bugiarda, ed è quello che salva più notti: rendere le operazioni ripetibili in sicurezza. Ricordi che, quando non ricevi risposta, non sai se il messaggio è arrivato, e sei tentato di rimandarlo? Il pericolo è fare la stessa cosa due volte: addebitare due volte un pagamento, spedire due volte un ordine. La soluzione è progettare ogni operazione perché ripeterla non faccia danni. Dai a ogni richiesta un'etichetta unica; quando arriva, la macchina controlla se ha già visto quell'etichetta, e se sì la ignora. Così puoi rimandare i messaggi con tranquillità, e la rete può pure consegnarli doppi: il risultato non cambia. È l'antidoto pratico ai duplicati, e non è un dettaglio: è una regola d'oro.
C'è un ultimo schema che vale la pena conoscere, per far respirare i pezzi tra loro: la coda di messaggi. Invece di far parlare due parti del sistema faccia a faccia, dove se una è lenta l'altra si blocca, ci metti in mezzo una lista d'attesa. Chi produce lavoro lo lascia nella coda e va avanti; chi lo consuma lo prende quando può. Così un picco improvviso non travolge nessuno, si accumula nella coda e viene smaltito col tempo, e se un consumatore cade il lavoro resta lì ad aspettarlo, non va perso. Abbiamo dedicato un'intera stagione a uno di questi sistemi di code, e qui ne vedi il ruolo: disaccoppiare, assorbire i picchi, non perdere niente.
Voglio lasciarti con il collegamento che rende tutto questo tuo, non astratto. Questi schemi non sono roba da giganti della Silicon Valley: sono gli stessi mattoni che usi tu. Il bilanciatore davanti alle tue applicazioni, la cache che alleggerisce il database, l'archivio diviso per chiave, la coda che smista i lavori pesanti, l'operazione resa ripetibile per sopravvivere ai tentativi ripetuti. Ogni volta che metti in piedi un servizio che deve reggere carico o restare in piedi quando qualcosa cade, stai applicando la teoria delle puntate scorse. Conoscerla per nome ti fa passare dal copiare ricette al capire perché quelle ricette funzionano, e quando invece non serve usarle.
Per oggi ci fermiamo qui. Abbiamo tradotto la teoria in schemi pratici della scala. Il primo è dividere i dati in fette, una per macchina, così ognuna gestisce solo la sua parte. Il secondo è distribuire il carico tra macchine gemelle e intercambiabili, con un vigile che smista, dove la sostituibilità rende tutto robusto. Il terzo è tenere copie di lettura vicino a chi legge, il caching su scala, accettandone il piccolo ritardo. Il quarto, che salva le notti, è rendere ogni operazione ripetibile in sicurezza con un'etichetta unica, l'antidoto ai duplicati della rete. E il quinto è la coda di messaggi, per disaccoppiare i pezzi e assorbire i picchi. Sono i mattoni che usi anche tu. Nella prossima puntata: non esiste il sistema distribuito perfetto. Nelle note trovi qualche spunto. Se ti è utile, condividila. Grazie per l'ascolto, e ci sentiamo alla prossima.