跳至正文
i@laoer.com

技术、生活、感悟 -- Laoer的博客

i@laoer.com

技术、生活、感悟 -- Laoer的博客

  • 首页
  • 关于
  • 首页
  • 关于
关

搜索

  • X
Web2.0构架设计

SNS中好友动态功能的设计思路

作者 Laoer
2009年3月17日 1 分钟阅读
13

现在大部分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中好友动态功能的设计思路,可能还有一些未想到的问题,还需要认真思考。

标签:

SNSWeb2.0
作者

Laoer

关注我
其他文章
上一个

IDEA中使用Tomcat不能启动的问题

下一个

PHP RSA研究

13 评论
  1. SNS中好友动态的架构设计 | 鸭嘴的blog说道:
    2009年4月13日 22:28

    […] SNS中好友动态功能的设计思路 […]

  2. elin说道:
    2009年5月18日 14:34

    我表的设计(部分)
    TrendType(反射到相应的类)
    objectId(主体,可以是用户,可以是其他任何)
    EventId 事件(某个object ‘s Title)
    EventBody( what…)
    …. 当然这个数据不管怎么样都会很大(前提这是个好网站,呵呵)首先一定要做表分区,之后做数据模版缓存,最后在呈现动态的时候保存当前动态(时间范围)(前提是有用户服务器,若干)

  3. 王涛说道:
    2009年8月1日 16:16

    说的很好。 我正在做一个这样的动态系统。 思路和你的好擦不多,当然没你想的这么深入。不过我想应该还有很多地方可以做优化。

  4. chuck911说道:
    2009年8月5日 11:10

    哈哈~博主你看看这片帖子:
    主题:请做架构的朋友一起讨论下SNS中好友动态功能建模的设计
    http://www.javaeye.com/topic/176677
    最后大家认同的方案是最简单原始的log表

  5. Suave’s Blog » Blog Archive » how to build activity-streaming说道:
    2009年8月7日 14:43

    […] http://i.laoer.com/sns-news-feed-design.html http://www.javaeye.com/topic/176677 http://stackoverflow.com/questions/202198/whats-the-best-manner-of-implementing-a-social-activity-stream http://stackoverflow.com/questions/624616/best-database-structure-for-storing-rss-feeds ruby on rails plugin: http://github.com/face/activity_streams/tree/master […]

  6. msgtype说道:
    2010年3月6日 03:12

    […] […]

  7. quady说道:
    2010年11月10日 22:22

    第二种方法感觉也有问题啊。
    譬如A加了B做好友,那会写入一条数据到EventUser吧,B就可以看到A的动态,但是A是看不到B的动态的

  8. DOOP说道:
    2010年12月9日 00:00

    为什么要在向Events表里插入数据的同时向EventUser表里写入好友对应数据了,可以在好支做出删除动作时再向EventUser里写入数据来记录哪个用户删了好友的动态。

  9. 盒子说道:
    2011年6月16日 00:42

    关注研究中。

  10. luo说道:
    2011年9月24日 20:18

    很喜欢你的文章
    能否在你的网站上做一个新浪微博的 分享按钮
    方便我分享给我朋友

  11. yiqing95说道:
    2011年12月3日 00:13

    不错 我也在考虑这个问题 至于分表 和异步写入 是在后期考虑的 前期用户量不大的话 可以先不用考虑 其实用nosql的话分表就不用考虑了
    这里我设计的表要比你这个多几张,所有的实体表 都继承自共有的模型 每个模型实现CRUD方法 每个CUD都会产生用户动作日志 user_op_log(id,uid,entity_class,entity_id,op_type,old_value,new_value,op_time); 比如上传图片 在模型层是操作的Picture这个模型 那么对于insert 和update delete 这样的动作都会触发op_event事件 由于我是在基类中捕获这样的事件 所以只做很少的动作 就可以形成用户的操作日志 这样用周期性任务定时处理操作日志,然后就是设计action_feed动作反馈表 因为用户跟好友分组属于一对多 广播性质的 反馈内容不能够重复不然太费空间了 只在id上重复即可 这里还牵扯 发布者/订阅者模式的实现 比如我要监听谁的动作 我的动作可以形成反馈给谁 都需要考虑 ,每个动作类型(action_type,entity_class的组合)对应一种通知模板 总共下来估计光表至少五六张 比较复杂的一个子系统啊 总的来说你的考虑也还算周全些 欢迎交流

  12. Shadowlong说道:
    2012年3月16日 10:13

    这个方法也是现在最常用的方法了, 不知道博主对微博这样的数据库设计以及方案有什么好看法?

  13. 刚子226说道:
    2015年10月29日 13:47

    好友动态表设计几点:
    1. 必须要有好友关系表
    2. 用户的动态信息表 (不同class的不同操作)
    3. 性能问题

    真对题主写的,基本赞同
    动态表可以用一条记录供所有人读取,也可以创建动态时给各个好友都发布一份

    各有优缺点,也需要根据实际情况应用

    另外最重要的就是考虑性能问题

显示评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

微信订阅

欢迎订阅微信公众号--“Laoer杂谈”,搜索微信号:laoertalk,“Laoer杂谈”是关于技术、创业、生活的杂谈与随笔,希望与大家多多交流。

用药有数·DoseLoop

用药有数·DoseLoop 一款不会响完就消失的用药提醒。每次计划用药持续追踪,直到有明确结果。支持慢病、老人、ADHD 等各种用药场景。

标签

AGI AI AI Agent Anthropic Claude Claude Code Codex DeepMind DeepSeek Gemini GLM Google GPT iOS iPhone IT Java JavaScript jQuery Kimi Kohana Linux LLM Mac Memcached Meta Mysql Nginx O2O OpenAI Oracle PHP RSA Sam Altman SNS Struts Tomcat Web2.0 互联网 人工智能 创业 工作 旅游 生活 管理

日历

2026 年 10 月
日 一 二 三 四 五 六
 123
45678910
11121314151617
18192021222324
25262728293031
« 9 月    

近期评论

  • AI数据分析如何改变BI工作流?15分钟完成一份运营报告 发表在《我把DeepSeek Harness接进生产环境后,发现AI运维真正改变的不是查日志》
  • 99%的代码都由AI写了,那程序员真正值钱的是什么? – i@laoer.com 发表在《我把DeepSeek Harness接进生产环境后,发现AI运维真正改变的不是查日志》
  • 爱生活 发表在《你的一分钟语音,可能是别人的十分钟》
  • 爱生活 发表在《Bill Gates为什么突然不相信“AI最终会创造更多工作”了?》
  • DeepSeek Harness来了,国产AI Coding终于开始补最短的那块板 – i@laoer.com 发表在《这次真不慌了,Claude随时可以取消订阅》
  • Kimi、GLM和Claude的差距,为什么每个人感受完全不同? – i@laoer.com 发表在《这次真不慌了,Claude随时可以取消订阅》
  • 携程被罚51.79亿元,酒店行业终于出了一口气 – i@laoer.com 发表在《萝卜快跑真的砸了底层劳动者的饭碗吗?》
  • Kimi卖爆之后,我发现AI可能不是一门互联网生意 – i@laoer.com 发表在《当中国开始开源最强模型,OpenAI和Anthropic的护城河还剩什么?》
  • Kimi卖爆之后,我发现AI可能不是一门互联网生意 – i@laoer.com 发表在《瓜子 vs 天天拍车:一次卖车体验的对比与思考》
  • 最强的模型,不一定能赢:AI Coding开始拼“好用”了 – i@laoer.com 发表在《一个人、一款 App、一个月:从 DoseLoop 看 AI 时代 OPC 的可能与边界》

分类

  • iOS
  • Java
  • JavaScript
  • Linux
  • Mac
  • PHP
  • Web2.0
  • 互联网
  • 人工智能
  • 创业
  • 博客文章
  • 商业观察
  • 工作
  • 数据库
  • 构架设计
  • 生活

归档

  • 2026 年 10 月
  • 2026 年 9 月
  • 2026 年 8 月
  • 2026 年 7 月
  • 2026 年 6 月
  • 2026 年 1 月
  • 2024 年 12 月
  • 2024 年 10 月
  • 2024 年 8 月
  • 2024 年 7 月
  • 2023 年 12 月
  • 2023 年 1 月
  • 2022 年 8 月
  • 2021 年 12 月
  • 2021 年 10 月
  • 2020 年 12 月
  • 2020 年 1 月
  • 2018 年 12 月
  • 2018 年 8 月
  • 2018 年 4 月
  • 2017 年 12 月
  • 2016 年 12 月
  • 2016 年 8 月
  • 2016 年 2 月
  • 2015 年 12 月
  • 2015 年 1 月
  • 2013 年 6 月
  • 2013 年 5 月
  • 2012 年 11 月
  • 2012 年 7 月
  • 2012 年 6 月
  • 2012 年 5 月
  • 2012 年 3 月
  • 2012 年 1 月
  • 2011 年 12 月
  • 2011 年 11 月
  • 2011 年 10 月
  • 2011 年 9 月
  • 2011 年 8 月
  • 2010 年 11 月
  • 2010 年 2 月
  • 2010 年 1 月
  • 2009 年 12 月
  • 2009 年 11 月
  • 2009 年 9 月
  • 2009 年 7 月
  • 2009 年 6 月
  • 2009 年 5 月
  • 2009 年 4 月
  • 2009 年 3 月
  • 2009 年 2 月

其他操作

  • 登录
  • 条目 feed
  • 评论 feed
  • WordPress.org
Copyright 2026 — i@laoer.com. All rights reserved. Blogsy WordPress Theme