2012-06-08 5 views
11

Ich bin derzeit interessiert zu sehen, welche Kanäle in einer Redis Pub/Sub-Anwendung abonniert sind, die ich habe. Wenn ein Client auf unserem Server verbindet, wir registrieren sie zu einem Kanal, der wie folgt aussieht:Redis publish/subscribe: Sehen Sie, welche Kanäle derzeit abonniert sind

user:user_id

Der Grund dafür ist, ich will in der Lage sein zu sehen, wer „online“ ist. Derzeit fange ich blind Nachrichten an einen Kanal ab, ohne zu wissen, ob ein Client online ist, da es nicht kritisch ist, dass sie diese Art von Nachrichten erhalten.

Um meine Anwendung intelligenter zu machen, möchte ich herausfinden können, ob ein Client online ist oder nicht die Pub/Sub-API verwendet, und wenn sie offline sind, ihre Nachrichten in einer separaten Redis-Warteschlange zwischenspeichern was ich ihnen schicken kann, wenn sie wieder online sind.

Dies muss nicht 100% genau sein, aber je genauer es ist, desto besser. Ich nehme an, dass ein generischer Schlüssel nicht erstellt wird, wenn ein Kanal abonniert wird, also kann ich nichts so trivial wie:

redis-cli keys user* tun, um alle Online-Benutzer zu finden. Die andere Strategie, an die ich gedacht habe, besteht darin, mein eigenes Redis-Set immer dann zu pflegen, wenn ein Benutzer sich selbst von einem Kanal veröffentlicht oder entfernt (was der Client automatisch behandelt, wenn er online springt und die App schließt). Das wäre eine zusätzliche Ebene der Komplexität, die ich verwalten muss, und ich hoffe, dass es einen trivialen Ansatz mit den Daten gibt, die bereits verfügbar sind.

Antwort

1

Mir ist keine spezielle Möglichkeit bekannt, abzufragen, welche Kanäle abonniert werden, und es ist richtig, dass in diesem Fall kein Schlüssel erstellt wird. Außerdem würde ich den Befehl KEYS sowieso nicht in der Produktion verwenden, da es sich wirklich um einen Debugging-Befehl handelt.

Sie haben die richtige Idee, ein Set zu verwenden, um den Benutzer hinzuzufügen, wenn sie online sind komm online.

Sie müssen herausfinden, wann sich ein Benutzer abmeldet, damit Sie sie aus der Liste der Online-Benutzer entfernen können, aber ich weiß nicht genug über Ihr System, um genau zu wissen, wie Sie das machen würden.

Wenn die verbundenen Clients die Möglichkeit haben, eine Nachricht zurückzusenden, um den Server darüber zu informieren, dass die Nachricht (en) verbraucht wurden, können Sie damit verfolgen, welche Nachrichten für den späteren Abruf gespeichert werden sollen.

Cheers, Mike

3

Es gibt derzeit keinen Befehl für die zeigen, was Kanäle „existieren“ haft abonniert werden, aber es ist und „genehmigt“ -Ausgabe und eine Pull-Anforderung, die diese implementiert.

https://github.com/antirez/redis/issues/221
https://github.com/antirez/redis/pull/412

Aufgrund der Natur dieses Aufrufs ist es nicht etwas, das skaliert werden kann, und ist somit ein „debug“ -Befehl.

Es gibt jedoch ein paar andere Möglichkeiten, um Ihr Problem zu lösen. Wenn Sie Grund zu der Annahme haben, dass ein Kanal abonniert werden kann, können Sie ihm eine Nachricht senden und sich das Ergebnis ansehen. Das Ergebnis ist die Anzahl der Abonnenten, die die Nachricht erhalten haben. Wenn du 0 hast, weißt du, dass sie nicht da sind.

Angenommen, Ihre user_ids sind inkrementell, möchten Sie möglicherweise SETBIT verwenden, um eine 1 oder 0 für das Offset-Bit eines Benutzers zum Nachverfolgen der Anwesenheit festzulegen. Sie können dann coole Dinge wie das neue BITCOUNT tun, um zu sehen, wie viele Benutzer online sind, und GETBIT, um festzustellen, ob ein bestimmter Benutzer online ist.

Die Art und Weise, wie ich Ihr Problem in der Vergangenheit genauer gelöst habe, besteht darin, einem Abonnement-Manager zu signalisieren, dass ich einen Kanal abonniert habe. Der Manager "pingt" dann den Kanal, indem er eine leere Nachricht sendet, um zu bestätigen, dass es einen Teilnehmer gibt, und pingt gelegentlich den Kanal danach, um festzustellen, ob der Benutzer noch online ist. Nicht ideal, aber besser als mit DEBUG CHANNELS in der Produktion.

+0

Großer Vorschlag! Ich hatte gerade das gleiche Bedürfnis und habe es geschafft, es zu schreiben, indem ich "null" auf dem Kanal veröffentlichte, um die Anzahl der Abonnenten zu erhalten. Dann überprüfe ich im Listener, ob die Nachricht "None" ist und überspringe sie, falls dies der Fall ist. Prost Kumpel! –

1

Ab Version 2.8.0 redis einen PubSub Befehl hat, die in diesem Fall helfen würde:

http://redis.io/commands/pubsub

Bemerkung: zur Zeit der Zustand von 2.8.0 ist noch nicht stabil (RC2)

4

ab Redis 2.8 können Sie tun:

PUBSUB CHANNELS [pattern] 

die PUBSUB CHANNELS command hat O (N) Komplexität, wobei N die Anzahl der aktiven Kanäle ist.

So in Ihrem Fall:

redis-cli PUBSUB CHANNELS user* 

würden Sie wünschen Sie wollen.