16
votes

I saw this snippet:

On Server

io.sockets.on('connection', function(socket) {
  const subscribe = redis.createClient();
  const publish = redis.createClient();

  socket.on('publish', function(channel, data) {
    publish.publish(channel, data);
  });

  socket.on('psubscribe', function(channel) {
    subscribe.psubscribe(channel);
  });

  subscribe.on("pmessage", function(pattern, channel, message) {
    socket.emit('message', { channel: channel, data: message });
  });
});

On Client

$(".action").click(function() {
  socket.emit('publish', 'game.#{gameid}.action.' + $(this).data('action'),
  JSON.stringify({ nick: "#{nick}", ts: Date.now() })
);

And I'm wondering why? Doesn't Socket.IO have its own broadcast mechanism? Why choose Redis' Pub-Sub over Socket.IO? Can't we just do like this:

io.sockets.on('connection', function(socket) {
  socket.on('action', function(channel, data) {
    socket.broadcast.to(channel).emit(data)
  });
});

And if there is a reason to use Redis, what would be the benefit? Persistence?

2
Your answer of "persistence" seems like a good one. Multi-process and multi-machine scaling is surely another.Richard Simões
Thanks! Did not think of the scaling issue.Sơn Trần-Nguyễn
Redis does not persist anything regarding pub/sub. It does not even queue the items in memory.Didier Spezia
What I was thinking is even when the server dies after receiving event from a client and fails to broadcast, with Redis, other clients will still receive it. But then, if redis client dies, then yeah, no persistence at all :( So that's not a strong reason there.Sơn Trần-Nguyễn
I think the main reason to use Redis here would be if there's a chance that non-sockets will want the information being broadcast. Redis works with other clients and would allow another applications you make to subscribe to what's happening. But without looking much into it, I'd have a glance at using RedisStore with socket.io (which has poor documentation) because I think that ends up using Redis' pub/sub system internally allowing for scalability.Pluckerpluck

2 Answers

16
votes

The reason I chose to use Redis Pub Sub with Socket.io in my Real Time Activity Stream project (http://blog.cloudfoundry.com/2012/06/05/node-activity-streams-app-2/) was because I wanted to have multiple web servers (instances on Cloud Foundry or dynos on Heroku). As far as I could see, Socket.io stores the messages in memory (of one webserver), so how it could possibly broadcast to clients which are connected to another webserver?

Check out the post and let me know if it helps

2
votes

Redis is used here for at least two reasons. The first one is that it works really well as a publish and subscribe mechanism, including being able to select messages based on pattern matching to psubscribe. The second reason is the ease of other clients to be able to publish and subscribe through the redis mechanism. That is not to say that it is impossible, just convenient. This combined with the asynchronisity of node.js makes a powerful partnership.

It's not the only solution of course but one that seems to work rather well.