Using redis in node.js chat app

1,020 views
Skip to first unread message

amer

unread,
Sep 2, 2013, 4:14:04 PM9/2/13
to redi...@googlegroups.com
Hi,

I implemented chat app for one website using node.js + javascript.
Now I need a way to store conversations messages, so when page refreshes, user can see all his conversations.
Actually, conversations should be saved based on session. During one server session, user can see all his conversations.
When he log out from page, all conversations should be destroyed.

I was looking for some king of storage for this messages and find that Redis should do job.
I found Redis client for node.js, but I don't understand it quite good.

Is the best way to store  and retrieve conversations using client put and get methods ?
So I don't use publishers and subsribers at all ?

And if someone can explain on simple example how subsribers and publishers work?

Thanks in advance

Aaron Meriwether

unread,
Sep 3, 2013, 12:43:24 PM9/3/13
to redi...@googlegroups.com
If you are using something like this Socket.io tutorial, then you are already using rudimentary pub/sub via the "io.sockets" object.

In pub/sub terminology, new connections get automatically subscribed to the global "io.sockets" list, and then when a later message is published via "io.sockets.emit()", it will be received by all clients.  Since node.js is single-threaded, it shouldn't be difficult to implement more complex pub/sub functionality directly in node.js, so until you need to scale beyond a single node.js instance, you probably don't actually need Redis for pub/sub at all. (But if you end up using Redis anyway for other persistence reasons, using it for complex pub/sub too isn't a bad idea).

As for storing per-user chat histories, you could use the "list" type in Redis (these examples assume you are using the "node_redis" client):
client.rpush(username, message) will allow you to add a string to a list for a particular user.
client.lrange(username, 0, -1) will allow you to retrieve the list of messages you have stored for a particular user.
client.del(username) will clear the list of messages stored for that particular user.

Note:
If you want to store something more complex than a simple string (for example, a data structure that contains a message plus the name of the user who wrote it), you can encode the structure as a JSON string before storing it in Redis. (node.js uses the V8 JS engine, so you can use the native JSON library)

-Aaron

amer

unread,
Sep 4, 2013, 3:29:12 PM9/4/13
to redi...@googlegroups.com
Hi,

Thanks for reply.
I wanted to know is there any way to store hash with lists as values in redis?
For example, something like:

client.rpush("conversations:"+conversation_id, message);

I wanted to store conversations in format of hash with id [sender_id]#[receiver_id]. That way when someone log in I get all conversations where that user is participant by running throught all conversations. This way I need some time to go thorugh all conversations and get only those for user. How this will affect performance ?

Or second way, maybe better way would be to store messages for user in format:

rpush(user_id, {sender: sen, receiver: rec, content: con, timestamo: tmstp})

This way I can easily recostruct all conversations for user and show them when user is logged in.
Advantage of this approach is that I need less time to get all user conversations (I get it directly from list), but this takes more space, because same message is saved twice, in sender's and receiver's message list.

What you mean, what is better approach?

Thanks in advance

On Monday, September 2, 2013 10:14:04 PM UTC+2, amer wrote:

Aaron Wirtz

unread,
Sep 4, 2013, 5:28:45 PM9/4/13
to redi...@googlegroups.com
Responses inline.

On Sep 4, 2013, at 9:29 PM, amer wrote:

Hi,

Thanks for reply.
I wanted to know is there any way to store hash with lists as values in redis?
For example, something like:

client.rpush("conversations:"+conversation_id, message);

That could work.

I wanted to store conversations in format of hash with id [sender_id]#[receiver_id].

You could use a unique integer as the ID.  That way you could support conversations with more than two participants. :-)
You can use the INCR command to generate sequential integers for use as IDs:

var conversation_id = client.incr("conversation_seq");

That way when someone log in I get all conversations where that user is participant by running throught all conversations. This way I need some time to go thorugh all conversations and get only those for user. How this will affect performance ?

Right.  If you wanted to store each conversation only once in order to save space, you would also need a way to link conversations with participants.  You could do that by maintaining a list of conversation_ids per user.

client.rpush("user_conversations:"+user_id, conversation_id);

Then you would be able to find all of a user's conversation_ids like this:

client.lrange("user_conversations:"+user_id, 0, -1);

And use those to fetch the contents of each conversation:

client.lrange("conversations:"+conversation_id, 0, -1);

Or second way, maybe better way would be to store messages for user in format:

rpush(user_id, {sender: sen, receiver: rec, content: con, timestamo: tmstp})

That was the format I was suggesting in the previous email:

client.rpush(user_id, JSON.stringify( {sender: sen, receiver: rec, content: con, timestamp: tmstp} ));

This way I can easily recostruct all conversations for user and show them when user is logged in.
Advantage of this approach is that I need less time to get all user conversations (I get it directly from list), but this takes more space, because same message is saved twice, in sender's and receiver's message list.

What you mean, what is better approach?

Which is the better approach will depend on what additional features you plan to add in the future.
The message-list-per-user would be the simplest to build.

Also, you may want to consider how you will handle clearing old conversations.
If you use the message-list-per-user format, each user could clear messages from their own history without affecting anyone else.

Thanks in advance

On Monday, September 2, 2013 10:14:04 PM UTC+2, amer wrote:
Hi,

I implemented chat app for one website using node.js + javascript.
Now I need a way to store conversations messages, so when page refreshes, user can see all his conversations.
Actually, conversations should be saved based on session. During one server session, user can see all his conversations.
When he log out from page, all conversations should be destroyed.

I was looking for some king of storage for this messages and find that Redis should do job.
I found Redis client for node.js, but I don't understand it quite good.

Is the best way to store  and retrieve conversations using client put and get methods ?
So I don't use publishers and subsribers at all ?

And if someone can explain on simple example how subsribers and publishers work?

Thanks in advance

--
You received this message because you are subscribed to a topic in the Google Groups "Redis DB" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/redis-db/-bv5SdAKdMo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to redis-db+u...@googlegroups.com.
To post to this group, send email to redi...@googlegroups.com.
Visit this group at http://groups.google.com/group/redis-db.
For more options, visit https://groups.google.com/groups/opt_out.

amer

unread,
Sep 5, 2013, 7:31:09 AM9/5/13
to redi...@googlegroups.com
Yes,

I thought about that also and approach with list of messages per user would be better solution in perspective of logout and destroying conversations.

But do you know some benchmarks on this topic ?
For example, if I have 1000 logged in users on my site in the same time, say they would run about 10000 conversations.
Duplicating of messages (same message for sender and receiver) may take lot of place for case like this.

In general, what is the limit of hash value in size in bytes ? I read somewhere that maximum is 4GB total (not for one value but whole database).
This is memory database, so it should depend on space of server RAM memory. 

I'm new to redis and I'm interested in it's performance and size of data it can store.

Thanks for previous replies and thanks in advance for reply on this post :)


On Monday, September 2, 2013 10:14:04 PM UTC+2, amer wrote:

Andy Lawman

unread,
Sep 5, 2013, 8:43:22 AM9/5/13
to redi...@googlegroups.com
4GB is a limit defined by a 32 bit address. If you're running on 32 bit hardware then that's your lot, if on 64 bit with a 64 bit OS then the practical limit is how much RAM you have in the box.

Andy.


--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages