关于类微博的timeline的设计思考
公司要开发一个类webio的系统,一个很基本的功能就是timeline。用户在自己的主页可以看到其观注的所有用户发表的信息列表;而其它用户可以一个用户的个人主页看到这个人发布的信息列表。
这时候最主要要考虑的就是采用推模式,还是拉模式。
一、推模式,以空间换时间;一个用户发布一条新信息之后,把这条信息追加到所有的粉丝的页面信息流里;这样当一个用户登录之后,通过一条fetch命令,就可以看他关注的所有人发布的信息了。但是这样一来,所带来的各种问题接踵而至:
1. 新关注一个用户时,需要把被关注的用户的所有历史数据都放到粉丝的数据流存贮里,在长时间后这是一个非常长的操作;
2. 取消关注一个用户时,需要把被取消关注的用户从原粉丝的数据流存贮里全部删除掉,这是一个O(N)的操作,而这个N的增加会很大;
3. 当一个用户删除一个已经分享的时候,需要将他的所有的粉丝的数据流里的这条记录都删除;
4. 一个用户的粉丝数是不受限制的,所以如果一个人的粉丝数过多的时候比如有1W个粉丝,那么发一条新消息,就要分解成1W次处理逻辑,工作量十分庞大。
所以就目前来看,不应该使用推模式,推模式带来的“坑”太多;
二、拉模式,空间消耗减小,时间消耗增加。 每个用户只存一个自己的timeline, 当一个用户打开自己的主页的时候,会把他关注的所有用户的数据取过来,然后进行合并,因为两个原因:1. 用户的数据存在redis里,存取速度十分快;2. 一个用户关注的用户数目是有限的(限制200人);
但是这时候存在的问题是,随着一个用户发的消息越来越多,用户的消息列表数据会越来越长,这时候merge所有一个用户关注的用户的信息过程会耗时非常长,而且消息列表数据长的时候,大数据网络传输也会特别耗时。
所以我认为在拉模式下,主要要修改用户发布的消息在redis里存贮的方式;
我的意见是在redis里以如下形式存贮:
userid_datetime –> user message list
即redis为每个用户存贮了每天的消息列表,这样就可以细化数据的粒度,减少每次取数据的数据量。
如此一来:
1. 当一个用户打开自己的主页的时候,只需要取他关注的用户当天的消息列表,这样的话取的数据量就会少很多,大大减少数据的传输和合并时间;如果当天数据不足,考虑再取前一天的数据;
2. 当打开一个用户的个人主页的时时候,可以考虑取最近10天的数据,不足的时候再动态加载。
而在页面展示的时候,可以突出时间的分隔点:
每天和每天的数据之意加一个突出的时间分隔符:
-----------> xxxx.xx.xz <------------------
…
…
…
-----------> xxxx.xx.xy <------------------
…
…
…
这样可以让用户非常直观的感觉到一个用户的数据发布时间轴,以及自己关注的用户的活动时间轴。
个人的一些观点。