🧪 Problem-Driven Systems Lab
🌧️ Caso 13 · Rendimiento

Cache stampede y thundering herd

Cuando la clave caliente expira, los N llamadores concurrentes recalculan el mismo valor y el origen recibe la rafaga entera.

OPERATIVO 🐘 PHP🐍 Python🟢 Node.js☕ Java🔵 .NET🐹 Go🦀 Rust

📈 Que cambia para el negocio

Evita caidas autoinfligidas en el momento de mayor fragilidad del sistema y reduce la capacidad reservada del origen.

💼 Que demuestra tecnicamente

Muestra que un hit rate del 99% no protege de nada si los fallos coinciden en el tiempo, y mide el arreglo con un solo numero.

✅ Evidencia que deja

  • Contrasta /cache-naive y /cache-singleflight sobre la misma rafaga con origin_computations como metrica central.
  • Hace visible stampede_depth, coalesced_waiters y served_stale en cada ejecucion.
  • Expone cache/state con soft TTL, hard TTL y el jitter aplicado por clave.

👀 Que mirar al ejecutarlo

  • Si origin_computations sube linealmente con concurrency en naive y se queda en 1 en singleflight.
  • Si coalesced_waiters da concurrency - 1: es la prueba de que el resto se colgo del mismo recalculo.
  • Si el double check dentro del vuelo esta presente en los siete stacks; sin el, el patron da 3 o 4 recalculos.
Honestidad: El origen es CPU real (un digest iterativo), no una consulta a una base de datos. Lo que se mide con fidelidad es origin_computations; la latencia absoluta depende del runtime y no es comparable entre stacks. En PHP los N llamadores se recorren en secuencia porque el servidor embebido es de un solo proceso.

Como esta resuelto en cada stack

Single-flight con la primitiva idiomatica de cada runtime: flock + double-checked locking en PHP, dict de vuelos con threading.Event en Python, Map<key, Promise> en Node, ConcurrentHashMap.computeIfAbsent atomico en Java, Lazy<Task<T>> con ExecutionAndPublication en .NET, singleflight escrito a mano con sync.WaitGroup en Go, Arc<Flight> con Mutex y Condvar en Rust

StackHealth check localComposeDetalle
🐘 PHP 8.3http://localhost:8100/13/healthcompose.root.ymlREADME del stack
🐍 Python 3.12http://localhost:8200/13/healthcompose.python.ymlREADME del stack
🟢 Node.js 22http://localhost:8300/13/healthcompose.nodejs.ymlREADME del stack
☕ Java 21http://localhost:8400/13/healthcompose.java.ymlREADME del stack
🔵 .NET 8http://localhost:8500/13/healthcompose.dotnet.ymlREADME del stack
🐹 Go 1.23http://localhost:8600/13/healthcompose.go.ymlREADME del stack
🦀 Rust 1.83http://localhost:8700/13/healthcompose.rust.ymlREADME del stack

El expediente completo

El caso no empieza en el codigo: empieza en el sintoma y termina en el postmortem.

← Caso 12Caso 14 →