Los principales beneficios de Redis son la velocidad y la funcionalidad. Redis es casi tan rápido como memcache (solo aproximadamente 0.1 ms más lento que memcache en el percentil 99 de latencia para recibir llamadas) y proporciona una amplia variedad de funciones de estructura de datos que lo extienden mucho más allá de un simple almacén de valores clave.
Sin embargo, Redis tiene algunas limitaciones que guiarán este análisis:
- Cada instancia de Redis tiene un solo subproceso. Esto significa que las consultas individuales que llevan mucho tiempo no son recomendables, ya que bloquearán otras consultas a la misma instancia de Redis hasta que se completen.
- El tamaño del conjunto de datos está limitado por la memoria disponible en la máquina en la que se ejecuta el servidor.
En un escenario de alto tráfico y gran conjunto de datos, casi seguramente tendremos que usar una instancia fragmentada para sortear estos límites. Redis se puede dividir de diferentes maneras (por ejemplo, utilizando Redis Cluster o twemproxy), pero muchos comandos de varias teclas no están disponibles a menos que el conjunto de datos esté cuidadosamente organizado y se usen claves de fragmentos, y la velocidad puede degradarse ya que se requiere más tráfico de red para ejecutar cualquier mando. Incluso en un entorno fragmentado, las consultas lentas bloquearán la ejecución de otras consultas en el mismo fragmento, por lo que aún debemos ser cuidadosos.
- ¿Por qué debería uno usar un marco de front-end MVC (como) para construir una aplicación web?
- ¿Cuál es la diferencia entre un sitio web y una aplicación?
- Cómo usar React / Redux con un backend de Golang
- ¿Cuál es la pila tecnológica más adecuada para el desarrollo web?
- ¿Cuál es la mejor aplicación de revisión en línea para agencias de publicidad?
Estas limitaciones significan que querremos usar Redis para datos estructurados de manera bastante simple que requieran un acceso rápido y no sean demasiado grandes. Redis se puede usar como caché con desalojo automático, como memcache, pero en Quora lo usamos como un almacén de datos persistente al deshabilitar el desalojo y guardar el conjunto de datos en el disco varias veces al día en las instancias esclavas. Algunos casos de uso que hemos desarrollado:
- Almacenar pequeñas cantidades de datos en una dimensión; por ejemplo, el último tiempo de acceso para cada usuario. Redis funciona bien aquí porque cada clave es muy pequeña (solo un número entero) e incluso con un billón de usuarios, todos los datos para estas claves caben fácilmente en la memoria de una máquina.
- Almacenar pequeñas cantidades de datos en dimensiones cero; por ejemplo, estado entre ejecuciones de un trabajo cron. Tenemos algunos crons que iteran sobre los usuarios, las preguntas y las respuestas creadas más recientemente, por lo que almacenamos la ID máxima examinada para cada uno de estos en Redis. También almacenamos información de monitoreo en Redis (por ejemplo, el último tiempo de verificación para varios servicios en nuestra infraestructura).
- Almacenar estado temporal que requiere acceso rápido; por ejemplo, las vistas de contenido más recientes. Almacenar todas las vistas de contenido en Redis para siempre sería ineficiente; muchos de estos valores se usan muy raramente y no necesitamos un acceso súper rápido a ellos. Almacenamos los recuentos de la vista de la verdad del terreno en HBase, pero es difícil para HBase manejar la carga causada por el aumento de los recuentos para cada vista en tiempo real. Por lo tanto, almacenamos las vistas en Redis y las volcamos cada minuto a HBase, agrupando los incrementos individuales en incrementos más grandes y reduciendo drásticamente la carga de escritura de HBase. (Consulte la Ingeniería del producto detrás de los escritores más vistos para obtener más información sobre el canal de vistas).
No queremos usar Redis para casos de uso como estos:
- Almacenar grandes cantidades de datos en un solo valor de cadena (por ejemplo, los contenidos de feed más recientes para cada usuario). Esto significa que las consultas en estas teclas serán lentas, lo que bloqueará otras consultas y, por lo tanto, ralentizará a todos los clientes.
- Almacenar datos en dos o más dimensiones (por ejemplo, una puntuación para cada par (usuario, tema)). El tamaño del conjunto de datos para estas claves probablemente crecerá de forma superlineal con el resto del conjunto de datos, y tendremos que buscarlo demasiado pronto.
- Almacenar datos que requieren consultas con alta complejidad de tiempo. Usar una lista Redis como cola está bien (las consultas al final de la lista toman tiempo constante), pero si la lista es larga, las consultas que operan lejos de los extremos de la lista o en toda la lista serán muy lentas. Algunos comandos tienen una complejidad de tiempo incondicionalmente alta (por ejemplo, SMEMBERS, HGETALL, KEYS) y queremos evitarlos por completo.
- Almacenar datos que requieren rutas de acceso secundarias. Redis no tiene índices secundarios ya que es un almacén de valores clave, por lo que tendríamos que implementarlos en el cliente, y usarlos requeriría múltiples consultas al servidor.
En un entorno de alto tráfico, hay algunas cosas a tener en cuenta que no son obvias a menor escala. Para nombrar unos pocos:
- El comando DEL puede ser lento. DEL no regresa hasta que se libera toda la clave, lo que puede tomar varios segundos si se trata de una lista o conjunto grande (> 1 GB más o menos). Para evitar esto, podemos usar LPOP / SPOP para iterar destructivamente la lista / conjunto. Esto es mucho más lento en el lado del cliente y requiere mucho más tráfico de red, pero se pueden ejecutar otras consultas mientras lo hacemos. Eliminar una gran cantidad de claves en una sola llamada DEL también es desaconsejable. (Redis 4.0 admite UNLINK, que soluciona este problema).
- Los scripts de Lua son atómicos, pero bloquean otras consultas mientras se ejecutan. Las secuencias de comandos que funcionan en varias claves también pueden fallar en un entorno fragmentado si las claves no están todas en el mismo fragmento. Evitamos scripts complejos por estos motivos; generalmente limitamos nuestros scripts para operar exactamente en una clave y tener una complejidad de tiempo hasta lineal en la longitud del valor de la clave (aunque esto también podría decirse que es peligroso).
- El guardado en segundo plano puede ralentizar notablemente la instancia, y el uso de la memoria aumentará lentamente hasta que esté hecho, debido a la semántica de copia en escritura de la bifurcación de Unix (). Si tenemos habilitado el sobrecompromiso de VM, no podemos permitir que el uso de memoria de nuestra instancia de Redis se acerque a la cantidad de memoria instalada, o no podremos guardar el conjunto de datos sin usar memoria virtual.
- La paginación de memoria virtual ralentiza a Redis y es inaceptable en un entorno de producción. Evitamos usar el disco en absoluto.
- Si utilizamos un enfoque de fragmentación basado en proxy, la reorganización es difícil y costosa. Escribimos un proxy de replicación en Quora que permite que un clúster fragmentado de Redis se replique desde otro clúster fragmentado con un número diferente de fragmentos, pero es mucho más lento que la replicación estándar: lleva casi un día sincronizar todo nuestro conjunto de datos a un nuevo clúster.
En resumen, Redis es apropiado para datos pequeños y simples que requieren un acceso rápido, pero en la mayoría de los entornos deben estar respaldados por otro almacén de datos más lento y menos costoso. En AWS, los datos almacenados en la memoria son aproximadamente 25 veces más caros que los datos almacenados en el disco, por lo que en Quora, utilizamos Redis como un almacén de datos independiente solo para datos sensibles al rendimiento, y preferimos MySQL o HBase para datos que pueden tolerar una mayor latencia de acceso .