Pregunta

¿Por qué Redis para hacer cola?

Tengo la impresión de que Redis puede ser un buen candidato para implementar un sistema de colas.Hasta este punto hemos estado usando nuestra base de datos MySQL con sondeo o RabbitMQ.Con RabbitMQ hemos tenido muchos problemas: las bibliotecas del cliente son muy pobres y tienen errores y nos gustaría no invertir demasiadas horas de desarrollador en solucionarlas, algunos problemas con la consola de administración del servidor, etc.Y, al menos por el momento, no nos estamos aferrando a los milisegundos ni a mejorar seriamente el rendimiento, por lo que mientras un sistema tenga una arquitectura que admita una cola de manera inteligente, probablemente estemos en buena forma.

Bien, ese es el trasfondo.Básicamente, tengo un modelo de cola simple y muy clásico: varios productores producen trabajo y varios consumidores consumen trabajo, y tanto los productores como los consumidores deben poder escalar de manera inteligente.Resulta ingenuo PUBSUB no funciona ya que no quiero todo suscriptores para consumir trabajo, solo quiero uno suscriptor para recibir el trabajo.A primera vista me parece BRPOPLPUSH Es un diseño inteligente.

¿Podemos utilizar BRPOPLPUSH?

El diseño básico con BRPOPLPUSH ¿Tiene una cola de trabajo y una cola de progreso?Cuando un consumidor recibe trabajo, empuja atómicamente el elemento a la cola de progreso y, cuando completa el trabajo, LREM'sentarse.Esto evita el bloqueo del trabajo si los clientes mueren y hace que el monitoreo sea bastante sencillo; por ejemplo, podemos saber si hay un problema que hace que los consumidores tarden mucho en realizar las tareas, además de saber si hay un gran volumen de tareas.

Se asegura

  • el trabajo se entrega exactamente a un consumidor
  • el trabajo termina en una cola de progreso, por lo que no puede quedar oculto si un consumidor

Los inconvenientes

  • Me parece bastante extraño que el mejor diseño que he encontrado en realidad no utilice PUBSUB ya que esto parece ser en lo que se centran la mayoría de las publicaciones de blog sobre las colas en Redis.Entonces siento que me estoy perdiendo algo obvio.La única manera que veo de usar PUBSUB sin consumir tareas dos veces es simplemente enviar una notificación de que el trabajo ha llegado, que los consumidores pueden luego sin bloquear RPOPLPUSH.
  • Es imposible solicitar más de un elemento de trabajo a la vez, lo que parece ser un problema de rendimiento.No es muy importante para nuestra situación, pero obviamente dice que esta operación no fue diseñada para un alto rendimiento o esta situación.
  • En breve: ¿Me estoy perdiendo algo estúpido?

También agrego la etiqueta node.js, porque ese es el lenguaje con el que trato principalmente.Node puede ofrecer algunas simplificaciones en la implementación, dada su naturaleza de subproceso único y sin bloqueo, pero además estoy usando la biblioteca node-redis y las soluciones también deben o pueden ser sensibles a sus fortalezas y debilidades.

¿Fue útil?

Solución

Si desea utilizar Redis para una cola de mensajes en Node.js y no le importa usar un módulo para eso, puede intentarlo RSMQ - la cola de mensajes simple de Redis para Node.No estaba disponible en el momento en que se hizo esta pregunta, pero hoy es una opción viable.

Si realmente quieres implementar la cola usted mismo como indicó en su pregunta, entonces es posible que desee leer la fuente de RSMQ porque son solo 20 pantallas de código que hacen exactamente lo que está solicitando.

Ver:

Otros consejos

Hasta ahora me he encontrado con algunas dificultades que me gustaría documentar aquí.

¿Cómo se maneja la lógica de reconexión?

Este es un problema difícil y especialmente difícil en el diseño e implementación de una cola de mensajes.Los mensajes deben poder ponerse en cola en algún lugar cuando los consumidores están desconectados, por lo que un simple pub-sub no es lo suficientemente fuerte y los consumidores deben volver a conectarse en un estado de escucha. Los pops de bloqueo son estados difíciles de mantener, porque son un estado de escucha no idempotente..Escuchar debería ser una operación idempotente, sin embargo, cuando se trata de una desconexión con respecto a un pop de bloqueo, se tiene el placer de pensar muy detenidamente si la desconexión ocurrió justo después de que la operación tuvo éxito o justo antes de que la operación fallara.Esto no es insuperable, pero sí indeseable.

Además, la operación de escucha debe ser lo más sencillo posible. Lo ideal es que tenga estas propiedades:

  • Escuchar es idempotente.
  • El consumidor es siempre La lógica de escucha y limitación se procesa fuera del código lógico de escucha.RabbitMQ encapsula esto permitiendo que el consumidor limite la cantidad de mensajes no codificados que puede tener.
    En particular, opté por un diseño deficiente en el que volver a ingresar a un pop bloqueado dependía del éxito de las operaciones anteriores, lo cual era frágil y requería pensar mucho.

Ahora prefiero una solución Redis PUBSUB + RPOPLPUSH.Esto desacopla la notificación de trabajo del consumo de trabajo, lo que nos permite factorizar una solución de escucha limpia. El PUBSUB sólo es responsable de la notificación de trabajos. La naturaleza atómica de RPOPLPUSH es responsable del consumo y delegar el trabajo a exactamente un consumidor.Al principio esta solución parecía innecesariamente complicada en comparación con un pop bloqueador, pero ahora veo que la complicación no era innecesaria en absoluto;estaba resolviendo un problema difícil.

Sin embargo, esta solución no es del todo trivial:

  • Los consumidores también deben verificar si hay trabajo en la reconexión.
  • Es posible que los consumidores quieran hacer una encuesta para nuevos trabajos de todos modos, por redundancia.Si la encuesta realmente tiene éxito, se debería emitir una advertencia, ya que esto sólo debería ocurrir entre el consumo en PUBSUB y la encuesta en un RPOPLPUSH.Por lo tanto, muchos éxitos en las encuestas indican que el sistema de suscripción no funciona.

Tenga en cuenta que el diseño PUBSUB/RPOPLPUSH también tiene problemas de escala. Cada El consumidor recibe una ligera notificación de cada mensaje, lo que significa que esto tiene un cuello de botella innecesario.Sospecho que es posible utilizar canales para fragmentar el trabajo, pero probablemente sea un diseño complicado para que funcione bien.

Entonces, la razón principal para elegir usar RabbitMQ en lugar de Redis son los escenarios de falla y la agrupación en clústeres.

Este artículo realmente lo explica mejor, así que solo proporcionaré el enlace:

https://aphyr.com/posts/283-jepsen-redis

Redis Sentinel y, más recientemente, la agrupación en clústeres de Redis no pueden manejar una serie de escenarios de fallas muy básicos que lo convirtieron en una mala elección para una cola.

RabbitMQ tiene su propio conjunto de problemas; sin embargo, dicho esto, es increíblemente sólido en producción y es una buena cola de mensajes.

Aquí está la publicación para conejo:

https://aphyr.com/posts/315-jepsen-rabbitmq

Cuando observa el teorema CAP (consistencia, disponibilidad y manejo de particiones), solo puede elegir 2 de 3.Estamos aprovechando RMQ para el CP (manejo de coherencia y partición) con nuestra carga de mensajes; si no estamos disponibles, no es el fin del mundo.Para no perder mensajes, utilizamos ignorar para el manejo de la partición para no perder mensajes.Se pueden manejar duplicados ya que la fuente administra el UUID.

Licenciado bajo: CC-BY-SA con atribución
scroll top