La caché es una memoria más pequeña y rápida que la de nuestro almacén de información, por lo que su uso se ha extendido desde el hardware hasta el software. Con la evolución de las tecnologías hacia internet y la utilización de diferentes servidores en entornos cloud, se ha creado la necesidad de desarrollar sistemas de caché distribuidos. Microsoft Azure nos provee de diferentes servicios de caché distribuida, pero debemos aprender a utilizarlos de la forma más eficiente. A lo largo de esta charla revisaremos los sistemas de caché disponibles y cómo podemos explotarlos en nuestras aplicaciones.
4. Agenda
Caché
¿Qué es?
Memory vs. no-memory
Tipos de datos
A fondo
¿Cómo usar la cache?
Patrón: cache-aside
¿Por qué usar cachés?
Caché moderna
Cachés distribuidas
Cachés en Microsoft Azure
Redis
Resumen
Pruebas
Conclusiones
Caché
¿Qué es?
Tipos de datos
A fondo
¿Cómo?
Patrones de diseño
¿Por qué?
Caché
moderna
Microsoft Azure
Redis
Resumen
Pruebas
Conclusiones
19. cache-aside pattern
1. Determinar si un objeto ya está
almacenado en la memoria caché.
2. Si no está almacenado en la memoria
caché leerlo del almacén de datos
3. Guardar el objeto que hemos cargado
en la memoria caché
?. Devolver el objeto almacenado en la
caché
21. Consideraciones a la hora de usar cachés
• Tiempo de vida de objetos en caché limitado
• Desalojo de datos
• Preparación inicial de caché
• Consistencia de la información
• Cachés locales
26. Pero:
Escalar es caro
Los procesos tienen límites
Los agregados no son la panacea
La sesión no es compartida
El output lo gestiona el cliente
36. Redis:
Es una base de datos NO-SQL que almacena información del tipo Clave/Valor.
37. Características de redis
• Maneja cadenas de texto (o byte arrays)
• 5 tipos de datos:
• Keys
• Hashes
• Lists
• Sets
• Sorted Sets
• Pub/Sub
• Operaciones con datos
• Scripts en LUA
• En memoria, pero persiste en forma de snapshots
39. Casos de uso de redis
• Listados de últimos xxx: LPUSH y LTRIM
• Tablas de top o de rankings: ZADD, ZREVRANGE y ZREVRANGEBYSCORE
• Cálculos de tipo “karma”: ZADD, ZRANK, ZINCRBY
• Contadores usuarios activos: INCR y EXPIRE
• Publicación y suscripción: mediator
• QUEUE’s (colas): BLPOP y LPUSH
• Textos auto-completables: ZADD, ZRANK y ZRANGE
• Almacenar información que caduca: EXPIRE
• …
Tokiota es una empresa joven que a lo largo de su año de vida ha conseguido un gran reconocimiento como especialistas en tecnologías Microsoft. Somos gold partners en movilidad (desarrollo de Windows pone y Windows Store), pertenecemos al azure circle y como partner preferente de Microsoft estamos especializados en:
Arquitectura de software
Soluciones Cloud
Infraestructura
Desarrollo en tecnologías Microsoft
Es un tipo de almacenamiento, pequeño, de acceso muy rápido que se utiliza en ingeniería de la computación para aportar una mayor velocidad al leer datos.
Cache L1: en el procesador, muy rápida, pero pequeña. Es la memoria donde el procesador almacena los registros con los que hace operaciones.
Cache L2: al lado de procesador, más grande pero más lenta. Aunque muy rápida. Es la típica caché que anuncian en los procesadores: i7 con 4kb de cache. Esta se usa como memoria intermedia, para almacenar más datos y luego volcarlos a la de nivel 1 para operar.
Cache L3: memoria RAM o de disco (la ram es más rápida que el disco). Este es el nivel donde los vamos a mover a lo largo de la charla. Es la caché que como programadores de lenguajes manejados, estamos capacitados para gestionar.
La memoria RAM a su vez tiene también una caché de acceso más rápido que la propia RAM, la SRAM, donde se almacenan los datos que más se usan. Y además puede usar la memoria de disco de la máquina si es que se ha llenado.
Y los discos usan como caché el típico buffer que se usa al leer un archivo.
Todo en los ordenadores usa siempre algún tipo de memoria caché :)
- Una cache física (no-memory) es aquella caché que se persiste en una unidad de almacenamiento. Fisicamente quedará almacenada hasta que caduque. Un ejemplo es el outPut caché de una página web. Al usar estos parámetros, los browsers entienden que esos datos no se van a modificar. Así que los guarda y no los vuelve a pedir al servidor, usa la copia almacenada en su caché. Aunque apaguemos el ordenador, estos datos no se borran, la próxima vez que iniciemos, estarán allí.
- La caché in-memory por otro lado, se almacena en la memoria RAM de la máquina. De forma que si reiniciamos la máquina, estos datos se borran y habrá que volverlos a cargar en la caché. Un ejemplo de esto sería el HttpRuntimeCache de asp.net: una caché que perdura en memoria y que gestiona por nosotros Asp.Net. Se le puede dar muchos usos, pero uno de los más típicos sería el ejemplo de un combo de países o ciudades. Datos que no suelen cambiar y que no queremos estar cargando constantemente de la base de datos. Los almacenamos en una memoria caché y accedemos a ellos de forma muy rápida.
Hay 3 tipos de datos que podría interesarnos almacenar en una memoria caché:
Datos de referencia: prácticamente de solo lectura. No se modifican demasiado y son comunes a todos los usuarios. Por ejemplo el listado de productos de una tienda virtual o los sprites/imagenes que luego se dibujan en pantalla en un videojuego.
Datos de actividad: son datos de lectura y escritura fundamentalmente, cuyo ciclo de vida es el mismo que el de la sesión de un usuario. Por ejemplo el carrito de la compra de una tienda virtual, o la puntuación de un jugador en un videojuego.
Datos de recursos: Son datos de lectura y escritura, compartidos por todos los usuarios, pero que pueden cambiar con frecuencia. Estos datos tienen la peculiaridad de poder ser accedidos por muchos usuarios. Un ejemplo sería el stockage de los productos de una tienda virtual, o las puntuaciones globales de todos los usuarios en un videojuego.
En resumen:
Está en manos del developer saber en cada momento y aplicación, qué datos sería mejor almacenar en qué tipo de caché. No hay una fórmula mágica para decidirlo, aunque sí algunos truquillos.
Lo que sí hay que tener en cuenta es que una caché in-memory puede perder los datos en algún momento, por lo que no tenemos la seguridad de que estén ahí siempre, aunque los hayamos almacenado ahí al iniciar la aplicación...
Tiempo de vida de objetos en caché limitado:
una gran parte de las memorias caché que existen implementan una política de expiración de los objetos que almacenamos en ella. Esto significa que un objeto tiene un tiempo de vida concreto. Si introducimos un valor de expiración muy alto, es posible que terminemos teniendo un objeto ya no válido. El uso de la caché está recomendado sobre todo para datos prácticamente estáticos o que se leen con mucha frecuencia.
Desalojo de datos:
también la mayoría de las cachés implementan un sistema automático de desalojo de objetos. Como la memoria de la caché es limitada, cuando esta se llena se opta por borrar los objetos más antiguos. Aunque podríamos implementar un modo de desalojo global, con un tiempo determinado para cualquier objeto, podría ser que haya objetos que sea recomendable saltarse estas limitaciones por razones de performance y de que el dato no varía con facilidad.
Preparación inicial de caché:
Muchos programas a la hora de arrancar realizan un llenado inicial de varios objetos en la memoria caché y alguno de ellos pueden ser usados en el proceso de inicio. Si usamos el patrón cache-aside, podemos garantizar que leemos correctamente estos datos aunque hayan caducado.
Consistencia de la información:
Lo primero que perdemos al utilizar memorias caché es la consistencia de los datos. No tiene por qué coincidir el objeto que está almacenado en caché con el que está en el almacén de datos. Y este problema se acentúa en la medida de la frecuencia de modificación de un dato que tenemos almacenado en la memoria caché.
Cachés locales:
Si usamos una aplicación con varios servidores balanceados y cada uno usa una caché local, además de tener un dato replicado en diferentes sitios, podría ser que existiera inconsistencia entre datos de la caché de un servidor y de otro. Esto tiene una fácil solución gestionando cachés distribuidas, como veremos más adelante.
Entonces, por qué usar una caché si puede dar tantos problemas?
Porque reducimos la latencia. Si la latencia es baja, las respuestas son más rápidas. Que las respuestas sean rápidas implica que la velocidad de la aplicación es mayor. Si tenemos una aplicación rápida, el usuario/cliente estará más contento. Y si el usuario/cliente está contento, significa que volverá a contar con nuestra aplicación o servicios de desarrollo.
Y esto en definitiva va a repercutir en más dinero para nosotros.
Escalando el sistema. Más hierro.
Mejorando la performance de los procesos
Almacenando y cargando agregados y no entidad por entidad
Usando variables de sesión o la caché output del asp.net
Escalar es caro.
Los procesos están limitados por la tecnología y los sistemas.
Almacenar agregados, tampoco nos va a aportar una velocidad tan grande, aunque es muy recomendable.
Las variables de sesión están solo disponibles para una instancia de una aplicación concreta, no para todas.
La caché output, la gestiona el cliente bajo unas directrices del servidor, pero no podemos borrarla bajo demanda. Solo el propio cliente es el que la puede manejar.
Como hemos dicho anteriormente, en los entornos actuales en los que una aplicación puede escalar en diferentes instancias, en los que tenemos sistemas híbridos cloud/on-premises o sistemas totalmente en la nube, las cachés locales in-memory se nos antojan algo desfasadas, ya que nuestras arquitecturas requieren de un solo componente que no tenga que estar replicado por cada una de las instancias de una aplicación, y es aquí cuando aparece una forma nueva de usar la caché:
Un sistema de Caché distribuido. Que no es más tratar la memoria caché como un nuevo aplicativo que consumen el resto de aplicaciones.
Pero manejar y darle disponibilidad a un sistema de caché distribuido puede ser un problema: nuevo hierro, problemas de gestión, hay que ver cómo integrarlo, tener un plan de escalabilidad y otro de contingencia para posibles problemas que surjan…
Y es aquí donde vemos que una gran solución para esto es usar servicios de caché en la nube
- Azure Cache (deprecated, pero mola hablar de ella. Es la de appFabric)
Si de hecho, funciona muy bien como cluster..
- Azure Cache InRole
- Azure Cache Services
- VM: cualquier sistema de cache, memcached.
- Redis: el uso definitivo? Yo lo preguntaría
Un sistema de Caché distribuido. Que no es más tratar la memoria caché como un nuevo aplicativo que consumen el resto de aplicaciones.
Pero manejar y darle disponibilidad a un sistema de caché distribuido puede ser un problema: nuevo hierro, problemas de gestión, hay que ver cómo integrarlo, tener un plan de escalabilidad y otro de contingencia para posibles problemas que surjan…
Y cómo no, como caché también se puede usar ;)
Si queréis saber algo más de redis y me aceptan la charla, podréis verlo en el evento de dentro de un mes, aquí en Madrid