我正在开发自己的社交网络,我还没有在网上找到用户操作流的实现示例...例如,如何过滤每个用户的操作?如何存储动作事件?我可以将哪种数据模型和对象模型用于操作流和自己的操作?
简介:对于大约100万活跃用户和1.5亿个存储活动,我保持简单:
使用关系数据库存储唯一活动(每个活动1个记录/"发生的事情")使记录尽可能紧凑.结构,以便您可以按活动ID或使用一组具有时间限制的朋友ID快速获取一批活动.
每当创建活动记录时,将活动ID发布到Redis,将ID添加到应该看到活动的朋友/订户的每个用户的"活动流"列表中.
查询Redis以获取任何用户的活动流,然后根据需要从db中获取相关数据.如果用户需要及时浏览(如果你提供这个),请回到查询数据库的时间
我使用一个普通的旧MySQL表来处理大约1500万个活动.
它看起来像这样:
id user_id (int) activity_type (tinyint) source_id (int) parent_id (int) parent_type (tinyint) time (datetime but a smaller type like int would be better)
activity_type
告诉我活动的类型,source_id
告诉我活动与之相关的记录.因此,如果活动类型表示"添加收藏",那么我知道source_id指的是收藏记录的ID.
的parent_id
/ parent_type
是我的应用程序非常有用-他们告诉我是什么活动有关.如果一本书被收藏,那么parent_id/parent_type会告诉我该活动与具有给定主键(id)的书(类型)相关
我索引(user_id, time)
和查询活动user_id IN (...friends...) AND time > some-cutoff-point
.抛弃id并选择不同的聚簇索引可能是一个好主意 - 我没有尝试过.
非常基本的东西,但它很有效,很简单,随着需求的变化,它很容易使用.此外,如果您不使用MySQL,您可以在索引方面做得更好.
为了更快地访问最近的活动,我一直在尝试使用Redis.Redis将所有数据存储在内存中,因此您无法将所有活动都放在那里,但是您可以存储足够多的网站上常见的屏幕.每个用户最近100个或类似的东西.使用Redis,它可能会像这样工作:
创建MySQL活动记录
对于创建活动的用户的每个朋友,将ID推送到Redis中的活动列表.
将每个列表修剪为最后的X项
Redis速度很快,并且提供了一种在一个连接上管理命令的方法 - 因此将活动推送到1000个朋友需要几毫秒.
有关我正在谈论的内容的更详细解释,请参阅Redis的Twitter示例:http://redis.io/topics/twitter-clone
2011年2月更新我目前有5000万活跃的活动,我没有改变任何事情.做类似的事情的一个好处是它使用紧凑的小行.我正在计划进行一些更改,这些更改将涉及更多活动以及对这些活动的更多查询,我肯定会使用Redis来保持速度.我在其他领域使用Redis,它确实适用于某些类型的问题.
2014年7月更新我们每月活跃用户约为70万.在过去的几年里,我一直在使用Redis(如项目符号列表中所述)存储每个用户的最后1000个活动ID.系统中通常有大约1亿个活动记录,它们仍然存储在MySQL中,并且仍然是相同的布局.这些记录让我们可以减少Redis内存,它们可以作为活动数据的记录,如果用户需要及时回页以查找内容,我们会使用它们.
这不是一个聪明或特别有趣的解决方案,但它对我有利.
这是我使用mysql实现的活动流.有三个类:Activity,ActivityFeed,Subscriber.
Activity表示一个活动条目,其表格如下所示:
id subject_id object_id type verb data time
Subject_id
是执行操作object_id
的对象的id,是接收操作的对象的id.type
并verb
描述了操作本身(例如,如果用户在文章中添加评论,他们将分别"评论"和"创建"),数据包含其他数据以避免连接(例如,它可以包含主题名称和姓,文章标题和网址,评论机构等).
每个Activity属于一个或多个ActivityFeeds,它们通过如下所示的表关联:
feed_name activity_id
在我的应用程序中,我为每个用户提供了一个提要,每个项目有一个提要(通常是博客文章),但它们可以是您想要的任何内容.
订阅者通常是您网站的用户,但也可以是对象模型中的任何对象(例如,文章可以订阅其创建者的feed_action).
每个订阅者都属于一个或多个ActivityFeeds,并且,如上所述,它们通过此类链接表相关:
feed_name subscriber_id reason
reason
此处的字段解释了订户订阅订阅源的原因.例如,如果用户为博客帖子添加书签,则原因是"书签".这有助于我稍后过滤用户通知的操作.
要检索订阅者的活动,我会对这三个表进行简单连接.加入很快,因为我选择的活动很少,这要归功于WHERE
现在的情况 - time > some hours
.由于Activity表中的数据字段,我避免了其他连接.
关于reason
领域的进一步解释 例如,如果我想要向用户过滤电子邮件通知的操作,并且用户将博客文章加入书签(因此他订阅了带有'bookmark'原因的帖子,)我不希望用户收到关于该项目的操作的电子邮件通知,如果他评论该帖子(因此它订阅了帖子提要的原因'评论')我希望当其他用户向同一帖子添加评论时,他会收到通知.reason字段帮助我进行这种歧视(我通过ActivityFilter类实现了它)以及用户的通知首选项.
当前正在由一群知名人士开发的活动流格式.
http://activitystrea.ms/.
基本上,每个活动都有一个演员(执行活动),一个动词(活动的动作),一个对象(演员在其上执行)和一个目标.
例如:Max发布了一个指向Adam墙的链接.
他们的JSON规范在撰写本文时已达到1.0版,它显示了您可以应用的活动模式.
他们的格式已被BBC,Gnip,Google Buzz Gowalla,IBM,MySpace,Opera,Socialcast,Superfeedr,TypePad,Windows Live,YIID等采用.
我认为关于通知系统如何在大型网站上运行的解释可以在堆栈溢出问题中找到社交网站如何计算朋友更新?在Jeremy Wall的回答中.他建议使用Message Qeue,他指出了两个实现它的开源软件:
的RabbitMQ
Apache QPid
另请参阅问题实施社交活动流的最佳方式是什么?