commands - Redis Pub/Sub con fiabilidad
redis vs mongodb (3)
He estado buscando usar Redis Pub / Sub como reemplazo de RabbitMQ.
Desde mi punto de vista, el pub / sub de Redis tiene una conexión persistente con cada uno de los suscriptores, y si la conexión se termina, todos los mensajes futuros se perderán y se perderán en el piso.
Una posible solución es usar una lista (y bloqueo de espera) para almacenar todo el mensaje y pub / sub como solo un mecanismo de notificación. Creo que esto me lleva la mayor parte del camino hasta allí, pero todavía tengo algunas preocupaciones sobre los casos de falla.
- ¿Qué sucede cuando un suscriptor muere y vuelve a conectarse? ¿Cómo debe procesar todos sus mensajes pendientes?
- cuando un mensaje mal formado llega a través del sistema, ¿cómo manejas esas excepciones? DeadLetter Queue?
- ¿Existe una práctica estándar para implementar una política de reintento?
Cuando muere un suscriptor (consumidor), su lista seguirá creciendo hasta que el cliente regrese. Su productor podría recortar la lista (desde cualquier lado) una vez que alcanza un límite específico, pero eso es algo que tendría que manejar a nivel de la aplicación. Si incluye una marca de tiempo dentro de cada mensaje, su consumidor puede actuar según la antigüedad de un mensaje, suponiendo que tiene una lógica de aplicación que desea imponer en la edad del mensaje.
No estoy seguro de cómo un mensaje mal formado podría ingresar al sistema, ya que la conexión a Redis suele ser TCP con sus garantías de integridad. Pero si esto sucede, tal vez debido a un error en la codificación del mensaje en la capa del productor, podría proporcionar un mecanismo general para manejar los errores al mantener una cola por productor que recibió los mensajes de excepción del consumidor.
Las políticas de reintento dependerán en gran medida de las necesidades de su aplicación. Si necesita 100% de seguridad de que un mensaje ha sido recibido y procesado, entonces debería considerar usar transacciones Redis (MULTI / EXEC) para ajustar el trabajo hecho por un consumidor, para que pueda asegurarse de que un cliente no elimine un mensaje a menos que ha completado su trabajo. Si necesita un reconocimiento explícito, puede usar un mensaje ACK explícito en una cola dedicada a los procesos del productor.
Sin saber más acerca de las necesidades de su aplicación, es difícil saber cómo elegir sabiamente. En general, si sus mensajes requieren una protección completa de ACID, entonces probablemente también necesite usar transacciones de redis. Si sus mensajes solo son significativos cuando son oportunos, entonces las transacciones pueden no ser necesarias. Parece que no puede tolerar los mensajes descartados, por lo que su enfoque de usar una lista es bueno. Si necesita implementar una cola de prioridad para sus mensajes, puede usar el conjunto ordenado (los comandos Z) para almacenar sus mensajes, usando su prioridad como valor de puntaje, junto con un consumidor de sondeo.
Lo que hice fue usar un conjunto ordenado usando la marca de tiempo como puntaje y la clave de los datos como valor del miembro. Utilizo el puntaje del último elemento para recuperar los siguientes y luego obtener las claves. Una vez que se termina el trabajo, envuelvo tanto el zrem como el del en una transacción MULTI / EXEC.
Esencialmente, lo que dijo Edward, pero con el giro de guardar las llaves en el conjunto ordenado, ya que mis mensajes pueden ser bastante grandes.
¡Espero que esto ayude!
Si desea un sistema de publicación / publicación en el que los suscriptores no pierdan mensajes cuando mueren, considere utilizar Redis Streams en lugar de Redis Pub / sub.
Redis Streams tiene su propia arquitectura y pros / contras a Redis Pub / sub. Con Redis Streams, un suscriptor puede emitir el comando:
el último mensaje que recibí fue X, ahora dame el siguiente mensaje; si no hay un mensaje nuevo, espere a que llegue uno.
El artículo de Antirez vinculado anteriormente es una buena introducción a las transmisiones de Redis con más información.
Advertencia: esta característica solo existe en la versión inestable (beta) de Redis como ahora.