web-dev-qa-db-fra.com

Redis Pub/Sub avec fiabilité

J'ai envisagé d'utiliser Redis Pub/Sub en remplacement de RabbitMQ.

D'après ce que j'ai compris, le pub/sous de Redis détient une connexion persistante avec chacun des abonnés. Si la connexion est interrompue, tous les messages futurs seront perdus et abandonnés. 

Une solution possible consiste à utiliser une liste (et une attente bloquante) pour stocker tout le message et pub/sub comme un simple mécanisme de notification. Je pense que cela me fait presque tout le chemin, mais je reste préoccupé par les cas d'échec.

  1. que se passe-t-il lorsqu'un abonné décède et revient en ligne, comment doit-il traiter tous les messages en attente?
  2. lorsqu'un message malformé parvient dans le système, comment gérez-vous ces exceptions? DeadLetter Queue?
  3. existe-t-il une pratique standard pour mettre en œuvre une stratégie de nouvelle tentative? 
38
Edward Chan

Lorsqu'un abonné (consommateur) décède, votre liste continuera de s'allonger jusqu'au retour du client. Votre producteur peut couper la liste (d’un côté ou de l’autre) une fois qu’elle atteint une limite spécifique, mais c’est quelque chose que vous devez gérer au niveau de l’application. Si vous incluez un horodatage dans chaque message, votre consommateur peut alors agir sur l'âge d'un message, en supposant que vous ayez une logique d'application que vous souhaitez appliquer à l'âge du message.

Je ne suis pas sûr de savoir comment un message mal formé entrerait dans le système, car la connexion à Redis est généralement TCP avec ses garanties d'intégrité. Mais si cela se produit, peut-être en raison d'un bogue dans le codage des messages au niveau de la couche producteur, vous pouvez fournir un mécanisme général de gestion des erreurs en conservant une file d'attente par producteur ayant reçu les messages d'exception du consommateur.

Les nouvelles tentatives dépendront grandement des besoins de votre application. Si vous avez besoin d'une assurance à 100% de la réception et du traitement d'un message, vous devez envisager d'utiliser des transactions Redis (MULTI/EXEC) pour boucler le travail effectué par un consommateur. Vous pouvez ainsi vous assurer qu'un client ne supprime pas un message sauf il a terminé son travail. Si vous avez besoin d'un accusé de réception explicite, vous pouvez utiliser un message ACK explicite sur une file d'attente dédiée au (x) processus producteur (s).

Sans en savoir plus sur les besoins de votre application, il est difficile de savoir comment choisir judicieusement. En règle générale, si vos messages nécessitent une protection ACID totale, vous devrez probablement également utiliser les transactions redis. Si vos messages ne sont utiles que lorsqu'ils sont à jour, les transactions peuvent ne pas être nécessaires. On dirait que vous ne pouvez pas tolérer les messages perdus, votre approche de la liste est donc bonne. Si vous devez implémenter une file d'attente prioritaire pour vos messages, vous pouvez utiliser le jeu trié (les commandes Z) pour stocker vos messages, en utilisant leur priorité en tant que valeur de score, avec un consommateur interrogateur.

34
Will Pierce

Ce que j'ai fait est d'utiliser un ensemble trié en utilisant l'horodatage comme score et la clé des données comme valeur de membre. J'utilise le score du dernier élément pour récupérer les prochains et récupérer les clés. Une fois le travail terminé, j’enveloppe à la fois le zrem et le del dans une transaction MULTI/EXEC.

Essentiellement, ce qu'Edward a dit, mais avec la torsion de stocker les clés dans l'ensemble trié, mes messages peuvent être assez gros.

J'espère que cela t'aides!

3
Hector Izquierdo

Si vous souhaitez un système de publication/sous-système dans lequel les abonnés ne perdent pas de messages lorsqu'ils meurent, envisagez d'utiliser Redis Streams au lieu de Redis Pub/sub.

Redis Streams a sa propre architecture et ses avantages/inconvénients par rapport à Redis Pub/sub. Avec Redis Streams, un abonné peut émettre la commande suivante:

le dernier message que j'ai reçu était X, donnez-moi maintenant le message suivant; s’il n’ya pas de nouveau message, attendez qu’il arrive.

L'article d'Antirez cité ci-dessus est une bonne introduction aux flux Redis avec plus d'informations.

Caveat: cette fonctionnalité n'existe que dans la version instable (bêta) de Redis.

0