El caché es una de las herramientas más seductoras en ingeniería de software. Con poco esfuerzo, transformas una operación lenta en una respuesta instantánea. El sistema se vuelve más rápido, la infraestructura respira, el usuario sonríe. Parece magia.
Y es precisamente porque parece magia que el caché causa tanto daño. Resuelve el problema de rendimiento con tanta facilidad que la gente reparte caché por todos lados, sin darse cuenta de que están intercambiando un problema visible, la lentitud, por un problema invisible, datos erróneos. Y los datos incorrectos son mucho peores que los datos lentos.
Esta es una guía rápida para utilizar bien el caché. La idea no es agotar el tema, sino darte los criterios que separan el caché que ayuda del caché que se convierte en trampa. Como dice el clásico chiste informático, sólo hay dos problemas difíciles: la invalidación de la caché, el nombramiento de cosas y el error uno más uno.
¿Qué hace el caché, en una oración?
El almacenamiento en caché consiste en guardar el resultado de una operación costosa para reutilizarlo, en lugar de rehacer la operación cada vez. Lo calculas una vez, lo guardas y la próxima vez entregas la respuesta guardada.
La operación "cara" podría ser una consulta pesada a la base de datos, una llamada a un servicio externo, un cálculo complejo o la representación de una página. La ganancia proviene de no repetir el trabajo. Cuando se solicita el mismo resultado muchas veces y cambia poco, el almacenamiento en caché casi siempre es una buena idea.
La palabra clave es "cambia poco". Ahí es donde radica toda la complejidad y ahí es donde la mayoría de la gente se equivoca.
Buena práctica: almacenar en caché lo que se lee mucho y cambia poco
El candidato de caché ideal tiene dos características: se accede a él con frecuencia y rara vez cambia. Piense en una lista de categorías de productos, la configuración de un sistema, el perfil público de un usuario. Este tipo de datos se leen todo el tiempo y se actualizan cada cierto tiempo, caché perfecto.
El candidato al mal caché es todo lo contrario: datos que cambian a cada instante o cuya precisión es crítica en tiempo real. El saldo de una cuenta bancaria, el stock disponible en el momento de la compra, el precio en una negociación activa, el almacenamiento en caché pueden dar al usuario una cifra que ya no es cierta, con consecuencias reales.
La pregunta práctica antes de almacenar en caché cualquier cosa: ¿qué sucede si el usuario ve un valor que está desactualizado durante unos segundos o minutos? Si la respuesta es "no es gran cosa", almacene en caché. Si la respuesta es "un problema grave", piénselo dos veces.
El verdadero problema: la invalidación
Poner datos en el caché es trivial. La parte difícil es saber cuándo eliminar o actualizar. Este es el problema de invalidación y es donde nacen casi todos los errores de caché.
Hay dos estrategias básicas y ambas tienen su lugar. El primero es el vencimiento del tiempo: los datos permanecen en la caché durante un período definido y luego se descartan. Sencillo, robusto y suficiente para la mayoría de casos. Acepta que los datos pueden estar desactualizados durante, digamos, cinco minutos y continúa con su vida.
El segundo es la invalidación de eventos: cuando los datos cambian, usted elimina o actualiza activamente la versión almacenada en caché. Es más preciso, pero más frágil, requiere que cada cambio en los datos recuerde notificarlo al caché, y todo lo que se necesita es una ruta olvidada para que el usuario vea la información antigua indefinidamente.
Mejores prácticas para una guía rápida: prefiera la caducidad programada siempre que la tolerancia lo permita. Es más simple, más resistente al error humano y evita la clase de error en el que el caché "olvida" actualizarse. Reserve la invalidación de eventos para cuando la precisión realmente justifique la complejidad.
Buena práctica: definir qué sucede cuando falla el caché
El caché es una capa adicional y las capas adicionales fallan. El servidor de caché puede dejar de funcionar, dejar de estar disponible o ser lento. La pregunta que mucha gente olvida responder: ¿entonces qué, se detiene el sistema?
El almacenamiento en caché bien hecho es una optimización, no una dependencia. Si el caché desaparece, la aplicación debe seguir funcionando, más lento quizás, pero funcionando, buscando datos de la fuente original. Cuando todo el sistema falla porque el caché falló, no tienes una optimización; tiene un único punto de falla disfrazado de mejora del rendimiento.
También hay un detalle traicionero: cuando el caché se vacía de una vez, todas las solicitudes llegan a la fuente original al mismo tiempo y la sobrecarga puede destruir precisamente lo que el caché protegía. Es un efecto conocido y vale la pena diseñar la recuperación teniendo esto en cuenta, para que el sistema recaliente el caché sin ahogarse.
Reflexión crítica: el caché oculta el problema incorrecto
Existe un uso del almacenamiento en caché que es a la vez técnicamente correcto y estratégicamente perezoso: el almacenamiento en caché para ocultar una consulta mal realizada. La consulta es lenta porque está mal escrita o la base de datos está mal modelada y, en lugar de corregir la causa, se le arroja caché. Funciona hasta que caduque el caché, hasta que aparezca el caso que no se puede almacenar en caché, hasta que el problema desaparezca.
La caché debería acelerar lo que ya es eficiente, no compensar lo que es ineficiente. Cuando te encuentras usando el caché para hacer soportable algo que debería arreglarse, vale la pena detenerse y analizar la causa. El caché, en este caso, es posponer una deuda, no pagarla.
También está el costo cognitivo. Cada capa de caché es una cosa más donde los datos pueden estar desactualizados, un lugar más para investigar cuando algo es extraño. "¿Por qué este usuario ve información antigua?" Es una de las cuestiones más frustrantes a la hora de depurar, precisamente porque el caché es invisible hasta que surge un problema. Demasiado caché convierte un sistema simple en un rompecabezas de versiones. Úselo con moderación, documente dónde se encuentra y prefiera menos capas bien comprendidas que muchas capas misteriosas.
Lo que queda
El caché es una herramienta poderosa y con la misma frecuencia se utiliza incorrectamente. Bien utilizado, deja sistemas rápidos y baratos. Se utiliza mal, proporciona información incorrecta, oculta problemas reales y crea errores difíciles de rastrear.
Las buenas prácticas caben en unas pocas líneas: almacenar en caché lo que se lee mucho y cambia poco; prefiera la caducidad programada a la invalidación manual; garantizar que el sistema sobreviva sin el caché; y nunca utilice el almacenamiento en caché para ocultar un problema que debería solucionarse. El resto es afinación.
Si enfrenta problemas de rendimiento y considera el almacenamiento en caché como una solución, primero vale la pena comprender si el cuello de botella se debe en realidad a lecturas repetidas o a algo más profundo. En el blog hay otros textos sobre backend, rendimiento y arquitectura que profundizan en estas opciones.
Lea también
- Backend para aplicaciones: buenas prácticas para equipos pequeños que no pueden cometer errores
- Caché en Aplicaciones: Buenas Prácticas y Fundamentos
- Caché en Aplicaciones: Buenas Prácticas y Pasos Esenciales
- Caché en aplicaciones
- Arquitectura de aplicaciones: Guía completa de sistemas escalables
- Escalabilidad de la aplicación: Guía técnica completa
