zoukankan      html  css  js  c++  java
  • SNS应用好友动态Feed模块设计

    转载自:http://libo93122.blog.163.com/blog/static/122189382012112145728902/

    备注:找不到原作者了。


    现在大部分SNS网站都有一个功能,就是显示好友的活动状态,比如你的好友上传了一张照片、分享了一篇文章等等动作,都可以显示在你的页面里,这样大大增强了社区的互动性,也成为现在SNS网站的主要特征,对于这样一个功能,从设计角度,还是值得思考的,并不简单,特别是用户越来越多,信息海量增长的时候,我未必能提出十全十美的方案,但我们可以由简如繁梳理一下思路。

    首先我们要定义用户的活动消息,也可以理解为一个事件,就是我们举的例子:用户上传照片、与别人结为好友、修改了个人资料等等,动作各有不同,但需要在结构上通用,我们先设计一个

    ID //消息ID
    UserID //用户ID
    MsgType //消息类型,比如加好友、上传照片等不同的类型
    EventMsg //消息的内容,这里我们可以用Json的数据格式来描述出不同的活动内容
    CreateTime //消息创建时间

    这个结构也是个数据库的结构,当用户做个一个动作之后,就会创建这样一个消息,并保存在数据库中,当显示好友的活动信息时,就从这张表里查询自己好友id的数据,并按时间显示,这个做法是一个最简单的实现,但会出现一些问题,当你与一个用户成为好友之后,该好友之前发生的动作会显示出来,而不是在成为好友时点之后的动作,同样,切断好友关系之后也有类似的问题,如果从业务角度和用户体验上可以接受的话,也没什么,但由于信息是按时间排序,有时候会给用户错乱的感觉,还有,这个信息不能删除,如果删除了所有好友就看不到这条信息了,但在Facebook里是则是可以删除好友的动作信息的,这个方法还有一个问题是,所有信息都放在一张大表里,在信息爆炸增长,个人好友也很多的情况下,查询效率会非常低,产生严重的性能障碍,如果对这张表做水平切分,则在实现上复杂了许多,性能也未必好很多,接下来我们再思考是否有更好的解决办法。

    在SNS的理论里,个人好友的合理数量在150个左右(最近有文章说Facebook的人均好友数是120人),SNS网站应该是有好友数量的限制的,我们就按人均150个好友来设想,是否可以在用户发生某些动作之后,针对他的所有好友都写入一条信息,所能解决的是,信息是在用户成为好友时点之后写入,用户可以删除好友的活动信息,不影响其他用户的显示,在显示时查询效率要高很多,但是负面效应也十分明显,一个用户的动作有平均150个写入,对于数据库来说开销也非常大,我们想想在这样的设计下,是否可以提高性能。

    首先看数据库设计,我们要把信息表和信息与用户的对应表分开,我们上面定义的数据结构保留,我们定义它的表名为Event,我们再新建一张表EventUser,结构如下

    ID  //主键
    EventID //Event表的ID
    FriendUserID //好友的ID
    CreateTime //消息创建时间

    对FriendUserID做索引,当用户发生动作时,首先将动作信息写入Event表,之后查找用户的所有好友,将EventID、好友ID逐条写入EventUser表,当要显示自己的好友活动信息是,查询EventUser中FriendUserID等于自己ID的信息,并和Event表做一个Join查询就可以了。

    进一步提升性能的方法,将Event里的信息缓存,比如用Memcached,EventID做为Key,内容做为Value,这样,查询EventUser是就不用Join Event表,而是从缓存里读取,由于要记录给每个好友的信息,所以EventUser会变得非常大,平均要比我们最初设计的数据容量大150倍,我们对EventUser表做水平切分,根据用户ID做Hash算法,基本上能均匀的分配到所有的表中,至于EventUser水平切分的算法还有多种,根据实际情况来定,总的来说就是把数据分摊掉,同时EventUser里的数据可以不永久保存,做定期删除,可以保持数据容量在一个合理的范围内。

    对于用户动作之后的数据写入,可以采用异步的方法,在发生动作时,抛出一个消息,由另外一个线程在做写入操作,如果对每个动作平均150次的写入仍存顾虑,我们可以针对每个用户开出一块内存空间,或是缓存,里面保存最后50条最新的好友动作,并在每条记录里做一个持久化标志,当有50条信息都标志是“未持久化”时,做一次数据库的写入,然后把信息置为“已持久化”,这种非实时写入的方式,可以提高一定的数据库效率,显示时,先从内存中取出,再查数据库。

    还有一些问题,对不不同消息类型的处理方式不同,比如用户修改个人资料,并不是每次发生这样的动作都要做一次给朋友做一次“群发”的操作,如果遇到这个人在短时间内做了多次修改个人资料的操作,就给朋友发出多个消息,会产生垃圾信息,让人觉得很怪异,所以对于这样的操作会有一定的时效性,比如在一天之内的修改个人资料,就是一个消息,这时候的处理是更新,而不是插入。

    以上是我对SNS中好友动态功能的设计思路,可能还有一些未想到的问题,还需要认真思考。



  • 相关阅读:
    loj#6433. 「PKUSC2018」最大前缀和(状压dp)
    PKUWC2019游记
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
    7. Reverse Integer
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/ycpanda/p/3637277.html
Copyright © 2011-2022 走看看