Question

Pourquoi Redis pour la file d'attente ?

J'ai l'impression que Redis peut être un bon candidat pour implémenter un système de file d'attente.Jusqu'à présent, nous utilisions notre base de données MySQL avec sondage, ou RabbitMQ.Avec RabbitMQ, nous avons eu de nombreux problèmes - les bibliothèques clientes sont très pauvres et boguées et nous aimerions ne pas investir trop d'heures de développement dans leur réparation, quelques problèmes avec la console de gestion du serveur, etc.Et, pour le moment du moins, nous ne cherchons pas à gagner des millisecondes ni à améliorer sérieusement les performances, donc tant qu'un système dispose d'une architecture qui prend en charge intelligemment une file d'attente, nous sommes probablement en bonne forme.

D'accord, c'est donc le contexte.Essentiellement, j'ai un modèle de file d'attente simple et très classique : plusieurs producteurs produisent du travail et plusieurs consommateurs consomment du travail, et les producteurs et les consommateurs doivent être capables d'évoluer intelligemment.Il s'avère naïf PUBSUB ça ne marche pas, puisque je ne veux pas tous les abonnés consomment du travail, je veux juste un abonné pour recevoir l'œuvre.Au premier passage, il me semble que BRPOPLPUSH est une conception intelligente.

Pouvons-nous utiliser BRPOPLPUSH ?

La conception de base avec BRPOPLPUSH est-ce que vous avez une file d'attente de travail et une file d'attente de progression.Lorsqu'un consommateur reçoit un travail, il place automatiquement l'élément dans la file d'attente de progression, et lorsqu'il termine le travail, il LREM's'asseoir.Cela évite le blackholing du travail en cas de décès des clients et rend la surveillance assez simple - par exemple, nous pouvons savoir s'il y a un problème qui fait que les consommateurs mettent beaucoup de temps à effectuer des tâches, en plus de savoir s'il y a un grand volume de tâches.

Il assure

  • le travail est livré à exactement un consommateur
  • le travail se retrouve dans une file d'attente de progression, il ne peut donc pas faire de trou noir si un consommateur

Les inconvénients

  • Il me semble plutôt étrange que le meilleur design que j'ai trouvé n'utilise pas réellement PUBSUB puisque cela semble être ce sur quoi se concentrent la plupart des articles de blog sur la mise en file d'attente sur Redis.J'ai donc l'impression qu'il me manque quelque chose d'évident.La seule façon que je vois d'utiliser PUBSUB sans consommer deux fois les tâches, il suffit d'envoyer une notification indiquant que le travail est arrivé, que les consommateurs peuvent ensuite envoyer de manière non bloquante. RPOPLPUSH.
  • Il est impossible de demander plus d'un élément de travail à la fois, ce qui semble être un problème de performances.Ce n'est pas un problème énorme pour notre situation, mais cela indique évidemment que cette opération n'a pas été conçue pour un débit élevé ou pour cette situation.
  • En bref: est-ce que j'ai raté quelque chose de stupide ?

Ajout également de la balise node.js, car c'est le langage avec lequel je travaille principalement.Node peut offrir quelques simplifications dans la mise en œuvre, étant donné sa nature monothread et non bloquante, mais j'utilise en outre la bibliothèque node-redis et les solutions devraient ou peuvent également être sensibles à ses forces et ses faiblesses.

Était-ce utile?

La solution

Si vous souhaitez utiliser Redis pour une file d'attente de messages dans Node.js et que cela ne vous dérange pas d'utiliser un module pour cela, vous pouvez essayer RSMQ - la file d'attente de messages simples Redis pour Node.Cette option n’était pas disponible au moment où cette question a été posée, mais elle constitue aujourd’hui une option viable.

Si tu veux réellement mettre en œuvre la file d'attente vous-même comme vous l'avez indiqué dans votre question, vous souhaiterez peut-être lire la source de RSMQ car ce ne sont que 20 écrans de code qui font exactement ce que vous demandez.

Voir:

Autres conseils

Jusqu'à présent, j'ai rencontré quelques difficultés que j'aimerais documenter ici.

Comment gérez-vous la logique de reconnexion ?

Il s’agit d’un problème difficile et particulièrement difficile dans la conception et la mise en œuvre d’une file d’attente de messages.Les messages doivent pouvoir être mis en file d'attente quelque part lorsque les consommateurs sont hors ligne. Un simple pub-sub n'est donc pas assez puissant et les consommateurs doivent se reconnecter en état d'écoute. Les pops bloquants sont un état difficile à maintenir, car il s'agit d'un état d'écoute non idempotent..L'écoute devrait être une opération idempotente, mais lorsqu'il s'agit d'une déconnexion par rapport à un pop bloquant, vous avez le plaisir de réfléchir très attentivement pour savoir si la déconnexion s'est produite juste après la réussite de l'opération ou juste avant l'échec de l'opération.Ce n’est pas insurmontable, mais ce n’est pas souhaitable.

De plus, l'opération d'écoute doit être aussi simple que possible. Idéalement, il devrait avoir ces propriétés :

  • L’écoute est idempotente.
  • Le consommateur est toujours l'écoute, et la logique de limitation est traitée en dehors du code logique d'écoute.RabbitMQ résume cela en permettant au consommateur de limiter le nombre de messages non confirmés qu'il peut avoir.
    En particulier, j'ai opté pour une conception médiocre dans laquelle la réentrée dans un pop bloquant dépendait du succès des opérations précédentes, ce qui était fragile et nécessitait une réflexion approfondie.

Je privilégie désormais une solution Redis PUBSUB + RPOPLPUSH.Cela dissocie la notification du travail de la consommation du travail, ce qui nous permet d'envisager une solution d'écoute propre. Le PUBSUB est uniquement responsable de la notification des travaux. La nature atomique de RPOPLPUSH est responsable de la consommation et de la délégation du travail à exactement un seul consommateur.Au début, cette solution semblait inutilement compliquée par rapport à un pop bloquant, mais maintenant je vois que la complication n'était pas inutile du tout ;cela résolvait un problème difficile.

Cependant cette solution n'est pas tout à fait triviale :

  • les consommateurs devraient également vérifier le travail de reconnexion.
  • Les consommateurs voudront peut-être de toute façon faire un sondage pour un nouveau travail, pour un licenciement.Si le sondage réussit, un avertissement devrait être émis, puisque cela ne devrait se produire qu'entre la consommation sur le PUBSUB et le sondage sur un RPOPLPUSH.Par conséquent, de nombreux sondages réussis indiquent un système d’abonnement défectueux.

Notez que la conception PUBSUB/RPOPLPUSH présente également des problèmes de mise à l'échelle. Chaque le consommateur reçoit une notification légère de chaque message, ce qui signifie qu'il y a un goulot d'étranglement inutile.Je soupçonne qu'il est possible d'utiliser des canaux pour partager le travail, mais c'est probablement une conception délicate à bien fonctionner.

Ainsi, la principale raison qui pousse à choisir d'utiliser RabbitMQ plutôt que Redis réside dans les scénarios de défaillance et le clustering.

Cet article l'explique vraiment mieux, je vais donc simplement fournir le lien :

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

Redis Sentinel et plus récemment Redis Clustering ne sont pas capables de gérer un certain nombre de scénarios d'échec très basiques, ce qui en fait un mauvais choix pour une file d'attente.

RabbitMQ a son propre ensemble de problèmes, mais cela étant dit, il est incroyablement solide en production et constitue une bonne file d'attente de messages.

Voici le post pour le lapin :

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

Lorsque vous examinez le théorum CAP (cohérence, disponibilité et gestion des partitions), vous ne pouvez en choisir que 2 sur 3.Nous exploitons RMQ pour le CP (cohérence et gestion des partitions) avec notre charge de messages, si nous ne sommes pas disponibles, ce n'est pas la fin du monde.Afin de ne pas perdre de messages, nous utilisons ignore pour la gestion des partitions afin de ne pas perdre de messages.Les doublons peuvent être gérés puisque la source gère l'UUID.

Licencié sous: CC-BY-SA avec attribution
scroll top