BookinglyTech News
Infraestructura

De 0,05 a 60 segundos por voto: un bucle de LPOP sin pausa contra Redis

Un post-mortem de depuración en EKS señala al culpable: tres workers lanzando LPOP no bloqueante en bucle cerrado saturaban Redis. Ni el balanceador ni los pods tenían la culpa.

2 min de lecturaDev.to0 vistas

El síntoma es de los que desesperan: después de un terraform apply y un kubectl apply, la aplicación responde y la página carga al instante, pero pulsar el botón de votar tarda a veces 5, 10 y hasta 60 segundos. Ningún pod aparece en mal estado en kubectl get pods y nada se cae. El autor del post reconstruye la secuencia de comprobaciones que llevó hasta la causa, y el culpable no era ni la red ni un contenedor concreto: era la forma en que los workers hablaban con Redis.

Fuera sospechosos: ni el balanceador ni un pod

La primera hipótesis fue el ELB clásico de AWS, que tarda unos minutos en registrar targets sanos después de crearse. Para comprobarlo sin adivinar se usó el desglose de tiempos de curl con -w, que separa lo que se tarda en abrir la conexión TCP de lo que se tarda en recibir el primer byte. El connect se mantuvo por debajo de 40 ms en todas las ejecuciones, mientras el ttfb llegó a 9,9 segundos. Eso descarta de golpe el balanceador, el DNS y la ruta de red.

Después llegó la sospecha típica de "hay un pod malo". El deployment corre tres réplicas repartidas en dos nodos, y nueve peticiones seguidas devolvieron, desde el mismo pod z5zqc, tiempos de entre 0,05 y 59,9 segundos. Un pod roto sería lento siempre, no instantáneo a ratos. El problema vivía en algo compartido por los tres.

Redis iba rápido, pero no paraba

La dependencia común era Redis, donde acaba cada voto. Un redis-cli --latency dio un mínimo de 0, un máximo de 31 y una media de 0,14 sobre 5.902 muestras. Como Redis es mono-hilo, una media baja no descarta que las órdenes hagan cola.

El redis-cli monitor enseñó el patrón real: los tres pods worker lanzando LPOP votes en bucle apretado, sin pausa ninguna. En tres segundos de captura, 7.571 líneas y 7.563 de ellas eran ese comando. LPOP no bloquea: si la lista está vacía, vuelve al momento. Y como los workers no tienen otra cosa que hacer, casi cada consulta encuentra la lista vacía y pregunta otra vez. Lo que correspondía era BLPOP, la versión que espera hasta que llegue un voto.

La comprobación de presión de CPU quedó a medias: kubectl top nodes y kubectl top pods fallan si no hay metrics-server instalado, y el relato original se corta justo cuando explica el recurso a /proc/loadavg.

Lo que queda claro es que una media sana en Redis no dice nada por sí sola. El comando que elige quien escribe el worker decide si Redis pasa el día ocioso o recibiendo miles de consultas por segundo que no encuentran nada.