node.js - example - nodejs redis cache
MongoDB y Redis como arquitectura de capa de caché (6)
Realmente depende de tus necesidades, pero aquí hay una bastante común:
on_get_request
if data_in_redis
serve_data_from _redis
else
get_data_from_mongo
set_data_in_redis
set_expire_in_redis
serve_data_from_memory
Los datos serán un poco rancios a veces, pero eso está bien para la mayoría de los casos de uso. Funciona bien en combinación con alguna invalidación de caché cuando se escriben datos importantes:
on_important_data
delete_invalid_redis_keys
Pero todo eso supone baja escritura, alta lectura y un conjunto estable de consultas.
¿Cómo se ve tu caso de uso de alta carga?
Supongamos que tenemos una aplicación de red social (que usa NodeJS, Express) y MongoDB como motor de base de datos principal.
En la mayoría de las llamadas API de clientes (aplicación móvil, aplicación web, etc.) no quiero hacer una consulta compleja para cada solicitud. Este tipo de solicitudes se pueden responder desde la capa de caché, Redis, por ejemplo.
Pero mi pregunta es cómo / cuándo debo actualizar la capa de caché, porque todas las operaciones de escritura se realizan en la base de datos MongoDB, no en la capa de caché (Redis). ¿Cuál es el enfoque / arquitectura correcta para abordar este problema?
¿Necesita transacciones y escrituras en tiempo real? Cuando alguien escribe una actualización sobre mongo, ¿es absolutamente necesario que los clientes sean notificados inmediatamente del cambio (1 segundo / minuto / día)?
¿Son sus datos realmente importantes que no se pierda ninguna escritura? Si es así, no puede escribir en redis primero excepto con AOF (que no es el modo predeterminado en redis y es mucho más lento). Las transacciones entre mongo y redis no serán tan fáciles de implementar, por ejemplo.
Si escribe en redis primero, puede usar publicar / suscribir para notificar a un cliente redis suscrito para actualizar el valor en mongo, pero no hay garantía de que sus datos se transfieran de manera segura, ¡tenga cuidado! Sin embargo, esa debería ser la forma más rápida / más eficiente de actualizar a todos sus clientes que están conectados a redis.
De otra forma, puede definir un sondeo con su intervalo aceptable en tiempo real entre redis y mongo para actualizar el caché con cambios de mongo a redis (desacoplamiento) sin escribir directamente en redis desde su código. Puede usar oyentes ("disparadores" en mongo) para hacerlo o usar un cheque sucio.
Finalmente, algunos han migrado de mongo + redis a couchbase como viber, ¿quizás deberías considerarlo como una opción? http://www.couchbase.com/viber
Esto ya está implementado en la arquitectura de referencia para el proyecto de código abierto MongoDB llamado "Socialite", aunque está en Java y no en node.js, así que mis respuestas se basan en mi experiencia de estrés y pruebas de carga de ese código.
Como puede ver en su implementación del feed de estado, el feed tiene la opción fanoutOnWrite cache que creará un caché (documento de tamaño limitado) para usuarios activos, limitando el número de entradas más recientes en el documento de caché (ese número es configurable).
Los principios clave de esa implementación son que los requisitos de contenido son de hecho diferentes de los requisitos de caché de línea de tiempo, y la base de datos de escritura en contenido es lo primero, ya que es el sistema de registro para todo el contenido, luego actualiza la caché (si existe). Esta parte se puede hacer de forma asíncrona , si se desea. La actualización utiliza "matrices limitadas", es decir, la funcionalidad de actualización $ slice, para aplicar atómicamente un nuevo valor / contenido a la matriz y cortar la más antigua al mismo tiempo.
No cree caché para un usuario si aún no existe (si nunca inician sesión, está perdiendo el esfuerzo). Opcionalmente puede caducar cachés basados en algún parámetro TTL.
Cuando vaya a leer un caché para un usuario cuando inicie sesión y no esté allí, vuelva a "fanoutOnRead" (que está consultando todo el contenido de los usuarios que siguen) y luego cree su caché para sacar ese resultado.
El proyecto Socialite usó MongoDB para todo el back-end, pero cuando lo comparó descubrimos que el caché de la línea de tiempo no necesitaba ser replicado o persistido para que sus servidores MongoDB estuvieran configurados para estar "en memoria" solamente (sin diario, sin replicación, sin disco lavado) que es análogo a su uso de Redis. Si pierde el caché, será reconstruido a partir del contenido permanente DB "on demand".
Ya que su pregunta es sobre arquitectura y comienza con "Supongamos ..."
¿Alguna razón para seleccionar mongoDB?
Con Postgres obtengo un mejor rendimiento que mongoDB y el mejor de los documentos relacionales y sin esquema con soporte de Postgres json / jsonb que es realmente más rápido que mongoDB. Con Postgres obtienes una base de datos de batalla FIABLE reforzada que tiene un excelente rendimiento, escalabilidad y lo más importante, te permite dormir por la noche y disfrutar de tus vacaciones.
También puede usar postgres LISTEN / NOTIFY para eventos en tiempo real para que pueda realizar el redis caché.
Aquí hay un ejemplo del uso de postgres ESCUCHAR / NOTIFICAR en nodejs: http://gonzalo123.com/2011/05/23/real-time-notifications-part-ii-now-with-node-js-and-socket-io /
Aquí hay algunos puntos de referencia de rendimiento integral para Postgres 9.4 como un documento schemaless / noSQL store vs mongoDB:
http://thebuild.com/presentations/pg-as-nosql-pgday-fosdem-2013.pdf
El enfoque Idel es una forma de escritura en caché. Puede escribir mongodb primero y luego escribir en redis. Es la forma más común.
Otra opción es, puede escribir redis primero y enviar un mensaje asincrónico usando redis (como Q). Algunos hilos pueden consumir el mensaje y leerlo, escribirlo en mongoDB.
La primera opción es más fácil de implementar. La segunda opción puede admitir un gran número de transacciones de escritura. Como sé, el problema de bloqueo de mongodb aún no está resuelto (se ha solucionado desde el bloqueo global al bloqueo de nivel de db). La segunda opción puede ser considerable para reducir dicha contención de bloqueo.
Se necesitaría un gran volumen de datos para hacer que Redis sea una opción viable para una capa de memoria caché sobre MongoDB, teniendo en cuenta que MongoDB tiene un conjunto de trabajo que se almacena en la memoria RAM; como tal, ambos pueden servir de memoria si sabes lo que estás haciendo y planificas bien tu esquema.
Normalmente, recurrir a Redis para el almacenamiento en caché es el objetivo de sitios masivos como craigslist ( http://www.slideshare.net/jzawodn/living-with-sql-and-nosql-at-craigslist-a-pragmatic-approach ), quien, como puede ver en la diapositiva 7 de esa presentación, utilícela para:
- contadores
- manchas
- colas
y más, pero puede ver fácilmente cómo su instalación de memcached también podría fusionarse con ella para incluir ciertas publicaciones también si MongoDB fuera su tienda primaria en lugar de MySQL.
Entonces, esa presentación en sí misma le da una buena idea de cómo otros usan Redis con MongoDB.
Básicamente, normalmente se usa para albergar instantáneas de datos que normalmente serían demasiado lentos para obtener de la base de datos.
Aquí hay información relacionada que usaré para responder mi pregunta un poco: ¿Qué es Redis y para qué lo uso? . Le recomiendo que lea esa pregunta, ya que le dará una idea más clara de para qué sirve el caso Redis y qué almacenamiento en caché podría hacer.