Quick and dirty Instant Messaging with Redis

Posted on Apr 22, 2010
(Aside: Yes this is a post after a zillion years, but I have a few more lined up, and waiting for some important stuff in about a week)

Redis is a wicked cool NoSQL database, in that storing stuff is not the only thing that it does. Mathias Meyer already has a collection of Redis use cases, but this great idea is mine. Like all good ideas it emerged in the shower :) ( I was not aware of Pieter Noordhuis' MUC when I did this, in either case mine deals with one-to-one IM )

Using the new publish-subscribe commands and a bit of node.js code, here is a tiny instant messaging server. An explanation follows, refer to the code while reading it, Blogger sucks for publishing code.

Here is how it works. For every client, the server maintains two connections to redis. This is because a subscriber is not allowed to invoke other commands. So we have a subscriber connection and publisher connection. Consider two clients are now connected, Alice and Bob.

When Alice connects ( NICK Alice ), we insert her nickname into 'mclarens:inside', a Redis set. This allows us to have a WHO command to list online members. Bob to does the same. To start chatting with Alice, Bob initiates a conversation ( TALKTO Alice ). The node server does none of its own client management. Instead each client just maintains subscriptions to two channels/classes. Each client is always subscribe to '[nick]:info', where it is notified of talk initiations and exits etc. When Bob wants to talk to Alice, he sends a 'start Bob' to Alice's info channel, 'Alice:info'. Then both Alice and Bob subscribe to the class 'Alice:Bob', using alphabetical order to decide the name. When either of them wants to talk to the other, they do MSG [nick] [message]. The connection uses the publish redis connection to send a message to the channel, resulting in both sides being notified of the incoming message.

To terminate the chat, one side just has to send a 'STOP [nick]'. That unsubscribes the user from the class so that he no longer receives messages. It also sends a 'stop [nick]' to the other side, so that he/she can also unsubscribe.

On QUIT, we simply remove ourselves from the mclarens:inside set, unsubscription is handled automatically by Redis!

That's it, simple Instant Messaging! Now this lacks any kind of security and ignore lists and status but proves the point. In fact I'm thinking of using this as the backend for the IM part of the XMPP server I'm hacking on. At this point it is in no shape to have this feature just yet, but it should some day.

(Thanks to roidrage and tnm on #redis for pointing out that I had to use two Redis connections for PubSub.)