Cuando trabajamos con Azure Cache for Redis en escenarios donde los datos cambian constantemente, las decisiones arquitectónicas se vuelven críticas. No se trata solo de montar un caché y olvidarse: hay que evaluar si realmente aporta valor, cómo manejar la concurrencia y qué políticas de expiración aplicar. Aquí se exploran las estrategias más relevantes para enfrentar estos retos sin caer en trampas comunes.
¿Por qué los datos altamente cambiantes son un escenario delicado para el caché?
Si los datos cambian todo el tiempo, surge una pregunta lógica: ¿tiene sentido montar un caché si hay que renovarlo constantemente? [0:18] El esfuerzo de leer desde la base de datos y recargar el caché puede superar el beneficio. Es un escenario adverso porque ir frecuentemente al origen de datos no siempre se traduce en una ventaja al usar caché.
Por eso, este análisis debe ser interdisciplinario. Las personas encargadas del caché, de la base de datos y del negocio deben participar en la toma de decisiones [0:52]. Nadie debería resolver estos problemas en solitario.
¿Qué significa realmente "ya" para el usuario?
No todos los escenarios requieren alta consistencia al milisegundo [1:12]. Estamos acostumbrados a que el software sea perfecto, pero en la práctica siempre hay tolerancias. Un ejemplo clásico: la tabla de países. Si Azerbaiyán no aparece por un instante, nadie se ve afectado.
La clave está en distinguir entre lo que "ya" significa técnicamente y lo que significa para el usuario:
- Para un sistema, "ya" puede ser un milisegundo.
- Para un usuario en una oficina, "ya" pueden ser cinco, diez o incluso treinta segundos [2:30].
- Hacer pruebas de campo con el usuario real permite definir esas tolerancias con precisión.
¿Se puede escribir primero en el caché?
Sí, y es perfectamente válido [3:08]. En lugar de escribir en la base de datos y luego refrescar el caché, se puede invertir el flujo:
- Escribir directamente en el caché para que todos vean la información actualizada.
- Usar una cola de mensajes (message broker) que en segundo plano sincronice con la base de datos.
- Un servicio en background recibe el mensaje, por ejemplo "adicionar cliente cincuenta", y ejecuta el insert en la base de datos.
Este patrón de microservicios con colas permite además manejar múltiples cachés dependientes o varios orígenes de datos [3:55]. Cada servicio actualiza lo que necesita de forma independiente. Es una estrategia poco utilizada pero muy poderosa para romper con el fixed mindset de que siempre hay que escribir primero en la base de datos.
¿Cómo manejar la concurrencia en Redis?
Cuando muchas personas y sistemas realizan transacciones al mismo tiempo, aparece un problema: las decisiones pueden basarse en valores que ya cambiaron [4:50]. Si leo una llave, tomo una decisión con ese valor y cuando voy a escribir el resultado alguien ya modificó esa llave, mi operación deja de ser válida.
Existen dos enfoques para manejar esto:
¿Qué es la concurrencia optimista?
Con la concurrencia optimista [5:48], confío en que la concurrencia no es tan alta como para impedirme operar:
- Leo la llave y obtengo su valor.
- Tomo mi decisión y realizo el cómputo.
- Justo antes de escribir, vuelvo a leer la llave para verificar que no haya cambiado.
- Si cambió, invalido y repito el proceso.
La ventaja principal es que no bloquea a nadie. Es un double check que funciona bien en escenarios con concurrencia moderada.
¿Cuándo usar concurrencia pesimista con bloqueo?
Cuando la concurrencia es tan alta que el enfoque optimista genera un ciclo indefinido de reintentos [6:45], se necesita la concurrencia pesimista. Aquí Redis ofrece instrucciones de bloqueo atómico:
- Leo la llave y la bloqueo simultáneamente.
- Realizo mi operación sin que nadie pueda modificarla.
- Escribo el resultado y libero el bloqueo.
Mientras la llave está bloqueada, cualquier otro proceso que intente escribir queda en espera. Se pueden configurar políticas de reintentos: intentar tres o cuatro veces y, si no se logra, devolver un error manejable [7:35].
El riesgo del bloqueo pesimista es dejar una llave bloqueada por un fallo inesperado. Si el cómputo falla después del bloqueo y nadie lo libera, se necesita monitoreo activo y acceso a la consola de administración para desbloquear manualmente [8:05].
¿Cómo definir políticas de expiración en escenarios de alta demanda?
La expiración de llaves añade transaccionalidad: cuando el caché expira, hay que recargar desde la base de datos [8:40]. En baja transaccionalidad esto funciona bien, pero con altísima demanda y tiempos de expiración muy cortos, se genera carga excesiva tanto en el caché como en la base de datos.
Alternativas para escenarios complejos:
- Manejar la expiración por software en lugar de depender de configuraciones globales en Redis.
- Basar la expiración en reglas de negocio específicas.
- Usar expiración por demanda: cuando ocurre un evento concreto, se invalida y recarga el caché [9:15].
Esto evita que una expiración global afecte a todos los consumidores de esa llave simultáneamente.
La mejor práctica que atraviesa todas estas decisiones es clara: involucren a todas las personas clave. Al de Redis, al de base de datos, al desarrollador y al de negocio. Muchas veces el problema se disuelve cuando alguien del equipo de negocio dice que ese módulo se usa una vez al mes o que pronto será reemplazado [9:50]. ¿Qué estrategia de concurrencia o expiración han aplicado en sus proyectos?