Implementing an Online Friends List

590 views
Skip to first unread message

John Chow

unread,
May 3, 2012, 7:20:45 PM5/3/12
to redi...@googlegroups.com
Hey Everyone,

I'm new to the Redis scene and I'm liking what I see so far (pub sub, downright sexy). Right now, I have a problem: how do you implement a online friends list i.e. Facebook Chat? Currently, I'm running a single Redis node (2.4.10) and I'm developing my app on Ruby (EventMachine + em-hiredis). My current online friends implementation was inspired by Luke Melia's blog post (http://www.lukemelia.com/blog/archives/2010/01/17/redis-in-practice-whos-online/), where I store each users' friend list in a set, and then intersect it with a "users_online" key. Everytime a user goes online/offline, I add/remove the user's id from the set.

I've ran preliminary tests on my local machine, and I get around 6000 q/s. I want to prepare for the case of 1 million users, and while 6000 q/s might be alright, I'm concern with how to scale this if the userbase grows.

If you have any suggestions, or even some reading material/real world examples, that'd help me greatly. Or if I'm totally on the wrong track, tell me I'm an idiot and I'll owe you big time.

Sorry if this is a nooby question y'all! I've been wracking my brain trying to think of a solution for this. Thanks for everyone's time!

John

alex

unread,
May 4, 2012, 3:36:56 AM5/4/12
to redi...@googlegroups.com
《Redis Presharding》 http://antirez.com/post/redis-presharding.html 
I think this artile woule be helpful to you.

在 2012年5月4日星期五UTC+8上午7时20分45秒,John Chow写道:

John Chow

unread,
May 9, 2012, 12:14:42 PM5/9/12
to redi...@googlegroups.com
@Alex, thanks for the good article read. It definitely helped me understand a lot more on scaling Redis.

I also realize that I re-posted this question in SO as well and that it could be viewed as spamming. To everyone, I apologize; I didn't intend nor realize that I was being inconsiderate. I've learned my lesson... I hope to update the answer in SO myself and share my experiences so others can benefit as well.

So I thought of a solution, and I hope I could get some feedback as to whether the idea is good or not, and if there are any pitfalls that I won't see until it's on production. Since our app needs relies very little on writes and more on reads, I figure to have one master node and many slave nodes. The master node will contain the current online list users:online (which would be stored as a set of string-integers under a single key), and a set of friend ids per user friends:#{user_id} (also stored as string-integers). Then our server app will round-robin the slave nodes and do a SINTER between the online list and that user's friend list.

Any feedback would greatly appreciated! Thanks everyone.

John

Josiah Carlson

unread,
May 9, 2012, 9:43:14 PM5/9/12
to redi...@googlegroups.com
That should handle your read scaling needs very well.

I would almost suggest writing your own custom server, but since your
set sizes are vastly different (a friends list vs. all online users),
that may not be reasonable.

As an alternative to always doing set intersections:
1. When a user X logs on, you intersect their friends set with the
online users to get their initial online set, and you keep it with a
Y-minute TTL (any time they do anything on the site, you could update
the expire time to be Y more minutes into the future)
2. For every user in that 'online' set, you find their similar
'initial set', and you add X to the set
3. Any time a user Z logs out, you scan their friends set, and remove
Z from them all (whether they exist or not)

With that change, you only do the relatively expensive set
intersection once during login, and the other parts (update friends'
sets on login/logout) can be done in a lua script, and should be
significantly faster (overall) than having to re-intersect for the
friends lists. The semantics of this makes it possible to still use
the master/slave setup for the set intersections, with a different
single Redis server to keep the up-to-date 'who of my friends are
online' sets.

As a point of comparison, on my Core 2 duo 2.4ghz desktop, I'm able to
perform some 61k "SADD <key> <20 values>" operations/second across 5
clients. Basically, as long as you have fewer than 61k login/logout
actions happening every second, a fairly modest box could be kept
reasonably up to date without issue, with a master and supporting
slaves to handle the initial set intersections.

Regards,
- Josiah
> --
> You received this message because you are subscribed to the Google Groups
> "Redis DB" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/redis-db/-/XEDiOfmqkIIJ.
>
> To post to this group, send email to redi...@googlegroups.com.
> To unsubscribe from this group, send email to
> redis-db+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/redis-db?hl=en.
Reply all
Reply to author
Forward
0 new messages