web-dev-qa-db-fra.com

Redis Pubsub et Message Queuing

Ma question générale est la suivante: En utilisant Redis pour PubSub, qu'arrive-t-il aux messages lorsque les éditeurs envoient des messages dans un canal plus rapidement que les abonnés ne peuvent les lire?

Par exemple, disons que j'ai:

  • Un simple éditeur publiant des messages au rythme de 2 msg/sec.
  • Un simple abonné lisant des messages à raison de 1 msg/sec.

Mon hypothèse naïve serait que l'abonné ne verrait que 50% des messages publiés sur Redis. Pour tester cette théorie, j'ai écrit deux scripts:

pub.py

queue = redis.StrictRedis(Host='localhost', port=6379, db=0)
channel = queue.pubsub()

for i in range(10): 
    queue.publish("test", i)
    time.sleep(0.5)

sub.py

r = redis.StrictRedis(Host='localhost', port=6379, db=0)
p = r.pubsub()
p.subscribe('test')

while True:
    message = p.get_message()
    if message:
        print "Subscriber: %s" % message['data']
    time.sleep(1)

Résultats

  • Quand j'ai couru sub.py d'abord, immédiatement suivi de pub.py, Je l'ai trouvé sub.py affiche en fait tous les messages (1-10), les uns après les autres avec un retard de 1 seconde entre les deux. Mon hypothèse initiale était fausse, Redis met les messages en file d'attente. Plus de tests nécessaires.
  • Quand j'ai couru pub.py d'abord, puis a attendu 5 secondes avant d'exécuter sub.py, Je l'ai trouvé sub.py n'affiche que la seconde moitié des messages (5-10). J'aurais supposé cela à l'origine, mais compte tenu de mes résultats précédents, j'aurais pensé que les messages étaient en file d'attente, ce qui m'a conduit à la conclusion suivante ...

Conclusions

  • Le serveur Redis semble mettre les messages en file d'attente pour chaque client, pour chaque canal.
  • Tant qu'un client écoute, peu importe la vitesse à laquelle il lit les messages. Tant qu'il est connecté, les messages restent en file d'attente pour ce client, pour ce canal.

Questions restantes

  • Ces conclusions sont-elles valables?
  • Si oui, combien de temps les messages client/canal resteront-ils en file d'attente?
  • Si oui, existe-t-il un redis-cli info commande pour voir combien de messages sont mis en file d'attente (pour chaque client/canal)?
47
Marco Benvoglio

Les tests sont valables, mais les conclusions sont partiellement fausses.

Redis ne met rien en file d'attente sur les canaux pub/sub. Au contraire, il a tendance à lire l'élément à partir du socket de l'éditeur et à écrire l'élément dans tous les sockets d'abonné, idéalement dans la même itération de la boucle d'événements. Rien n'est conservé dans les structures de données Redis.

Maintenant, comme vous l'avez démontré, il existe encore une sorte de tampon. Cela est dû à l'utilisation des sockets TCP/IP et des tampons de communication Redis.

Les sockets ont des tampons, et bien sûr, TCP est livré avec des mécanismes de contrôle de flux. Il évite la perte de données lorsque les tampons sont pleins. Si un abonné n'est pas assez rapide, les données s'accumulent dans son socket Quand il est plein, TCP bloquera la communication et empêchera Redis de pousser plus d'informations dans le socket.

Redis gère également les tampons de communication de sortie (au-dessus de ceux des sockets) pour générer des données formatées avec le protocole Redis. Ainsi, lorsque le tampon de sortie du socket est plein, la boucle d'événements marquera le socket comme non accessible en écriture et les données resteront dans les tampons de sortie Redis.

À condition que la connexion TCP soit toujours valide, les données peuvent rester dans les tampons pendant très longtemps. Maintenant, le socket et le tampon de sortie Redis sont liés. Si les abonnés sont vraiment trop lents et beaucoup de données s'accumulent, Redis fermera finalement la connexion avec les abonnés (comme mécanisme de sécurité).

Par défaut, pour pub/sub, Redis a une limite logicielle à 8 Mo et une limite stricte à 32 Mo, par tampon de connexion. Si le tampon de sortie atteint la limite stricte, ou s'il reste entre la limite souple et la limite stricte pendant plus de 60 secondes, la connexion avec l'abonné lent sera fermée.

Il n'est pas facile de connaître le nombre de messages en attente. Il peut être évalué en examinant la taille des informations en attente dans les tampons de socket et les tampons de sortie Redis.

Pour les tampons de sortie Redis, vous pouvez utiliser la commande CLIENT LIST (de redis-cli). La taille du tampon de sortie est renvoyée dans les champs obl et oll (en octets).

Pour les tampons de socket, il n'y a pas de commande Redis. Cependant, sous Linux, il est possible de construire un script pour interpréter le contenu du fichier/proc/net/tcp. Voir un exemple ici . Ce script doit probablement être adapté à votre système.

87
Didier Spezia