Tag: scalability, architecture, distributed-systems, backend, performance, caching
Livello: intermedio
TL;DR: Principi di scaling orizzontale e verticale, gestione dello stato, caching, partizionamento dei dati e disaccoppiamento asincrono.
Scalabilita verticale (scale up): aumento di CPU, RAM o disco sulla singola istanza.
Scalabilita orizzontale (scale out): aggiunta di nodi computazionali dietro un load balancer.
Stateless architecture: delegare sessioni e stati ad archivi centralizzati per permettere scaling orizzontale istantaneo.
Load balancing: distribuzione del traffico tramite algoritmi Round Robin, Least Connections o IP Hash.
Caching multi-livello: memoria applicativa locale, cluster distribuiti (Redis/Memcached) e CDN edge caching.
Database scaling: replica in lettura (Read Replicas) per carichi read-heavy.
Database sharding: partizionamento orizzontale dei dati basato su shard key per write-heavy.
Disaccoppiamento asincrono: code di messaggi (RabbitMQ, Kafka, SQS) per livellare picchi e assorbire carichi improvvisi.
Database connection pooling: prevenzione dell'esaurimento socket sotto alto traffico concorrente.
Rate limiting e throttling: protezione dei servizi critici dal sovraccarico computazionale.
Q: Come affronti il problema della scalabilita di una web application monolitica?R: Rimuovo lo stato in memoria spostando sessioni su Redis, introduco un reverse proxy/load balancer e configuro read replicas per le letture del database.
Q: Quando conviene scalare verticalmente rispetto a orizzontalmente?R: Lo scale up e' rapido e riduce la complessita architetturale iniziale, ma ha un tetto hardware; passo a scale out appena servono alta disponibilita e carichi distribuiti.
Q: Come gestisci i colli di bottiglia causati da scritture frequenti sul database?R: Implemento code asincrone per buffering, valuto sharding su base tenant/entita e uso scritture in batch o database orientati all'append-only.
Salvare stato utente o file direttamente sul filesystem locale del server applicativo.
Mancanza di indici appropriati nel database scambiata erroneamente per saturazione hardware.
Thundering herd problem: scadenza simultanea di chiavi in cache che travolge il database primario.
Scelta errata della shard key, che porta a hotspot su un unico nodo del cluster.
Mancata gestione del backpressure nei consumer di messaggi asincroni.
Session stickiness prolungata sul load balancer che sbilancia il traffico tra nodi.
// Pattern cache-aside con fallback e time-to-live
async function getUserData(userId: string): Promise<User> {
const cacheKey = `user:${userId}`;
const cached = await redis.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
const user = await db.user.findUnique({ where: { id: userId } });
if (user) {
await redis.set(cacheKey, JSON.stringify(user), 'EX', 3600);
}
return user;
}
Bash
# Test di carico rapido via Apache Bench per verificare throughput
ab -n 10000 -c 100 http://localhost:8080/api/health
[ ] Pattern di caching: Read-Through, Write-Through e Write-Behind
[ ] Teorema CAP e implicazioni di consistenza eventuale
[ ] Algoritmi di consistent hashing per lo sharding
[x] Differenza pratica tra scale up e scale out
[x] Utilizzo di message broker per il livellamento del traffico