Tag Archives: Cache

Utilizar MongoDB como sistema de caché

Prácticamente cualquier servicio online con un mínimo de tráfico y de complejidad requiere de un sistema de cache para aligerar su carga y reducir el tiempo de respuesta de ciertas peticiones, que deben ser aquellas peticiones más comunes y aquellas más costosas en cuanto a recursos que consumen.

En este punto siempre surge la incógnita sobre que sistema de caché utilizar, y factores como el tamaño y la estructura de los datos, o la velocidad de lectura y escritura son variables que debemos tener en cuenta a la hora de elegir uno.

Una muy buena opción desde mi punto de vista es utilizar Mongo para cachear datos. La idea es que tienes una colección por cada tipo de información que quieres cachear:

db.micache = {  
   _id:String,
   datos: { 
      ... todo lo que queremos cachear ...
   },
   fecha:Date
}

Donde:

  • El _id es de tipo String y es una cadena de caracteres en cuya generación participan todas las variables que influyen en el resultado a cachear. Es decir, si por ejemplo queremos cachear los contactos de un usuario, el _id debe ser generado con el identificador del usuario, algo del estilo “contacts_007”. Otro ejemplo sería si quisiéramos cachear los contactos compartidos por dos usuarios diferentes cualesquiera, en este caso generaríamos algo como “shared_007_x_199”, que almacenaría datos diferentes a otra entrada que podría ser “shared_007_x_203”.
  • En datos guardaremos lo que queramos cachear, sea del tipo que sea, aprovechando la flexibilidad de Mongo que nos va a permitir almacenar cualquier cosa sin tener que definir ningún esquema previo. Además otra de las ventajas de Mongo es que los datos guardados pueden ser del tamaño que queramos, sin importar lo grandes que sean.
  • Por último en fecha se almacenará la fecha de creación del objeto cacheado, y además crearemos un índice con tiempo de expiración, para que sea el propio Mongo automáticamente el que borre de caché los objetos que hayan cumplido el tiempo de expiración. En la siguiente línea decimos que cualquier documento guardado expirará a los 14.400 segundos, es decir, estamos creando una cache de 4 horas.
db.micache.createIndex( { "fecha": 1 }, { expireAfterSeconds: 14400 } )

 

Las ventajas que aporta esta solución son:

  • Es extremadamente flexible en cuanto a la estructura de datos a guardar. Texto, números, mapas, listas, cualquier tipo de estructura puede guardarse directamente en Mongo, y será aquel que lo guarde y recupere el que le sepa como manejarlo.
  • Disponemos de una capacidad de almacenamiento muy alto, no limitado a la memoria RAM que tengamos disponible. El disco es más barato que la memoria, y nos va a permitir cachear sin tener que preocuparnos prácticamente por lo que consumamos.
  • Si estamos utilizando un Replica Set de Mongo, tendremos además un sistema de cache con alta disponibilidad y escalable, ya que podemos distribuir las lecturas entre los nodos secundarios. Además si añadimos un nuevo servidor de aplicaciones, o tenemos que reiniciar alguno, tendrá inmediatamente toda la información cacheada a su disposición, lo que no ocurriría si cada servidor de aplicaciones guarda su cache en su memoria local.

El inconveniente que le podemos atribuir es:

  • Al ser acceso a disco no será tan rápido como es el acceso a memoria, pero como siempre vamos a acceder por _id será suficientemente rápido para la mayoría de los casos requeridos.

Yo lo estoy utilizando en sistemas en producción con un excelente resultado.

Advertisements