设计新闻推送系统(第二部分)
原文:Design News Feed System (Part 2)
译者:飞龙
自豪地采用谷歌翻译
这是系统设计面试问题分析 - 设计新闻推送系统的第二部分。如果你还没有看我们的第一篇文章,请查看它。
这里只是简要地总结一下我们在第一部分中讨论过的内容。我们从一个简单的问题开始 - 如何设计 Facebook 的新闻推送系统,允许用户看到来自好友的推送/更新。我们使用关系数据库对整个系统进行建模,并讨论了不同设计的优缺点。
排名是新闻推送系统的一个有趣的话题。我们在前一篇文章中解释了一些整体的排名思路。在这篇文章中,我们将继续讨论排名,还包括推送发布等主题。
排名 - 续
排名的整体思路是首先选择相关的特征/信号,然后弄清楚如何组合它们来计算最终分数。这种方法在很多现实系统中非常普遍。
正如你所看到的,这里重要的是两件事情 - 特征和计算算法。为了让你更好地了解它,我想简单介绍一下 Facebook 上的排名实际上的工作方式 - EdgeRank。
对于每个新闻更新,当其他用户与该推文交互时,他们正就创建了一个东西,Facebook 称之为“边”,其中包括例如喜欢和评论之类的操作。
首先,我们来看看使用哪些特性来评估更新/推送的重要性。边的排名基本上是使用三个信号:亲密度,边权重和时间衰减。
- 亲密度(
u
)。对于每个新闻推送源,亲密度都会评估你与此用户的距离。例如,你更可能关心你的亲密好友的推送,而不是刚刚遇到的人。你可能会问如何计算亲密度,我很快会讨论它。 - 边权重(
e
)。边权重基本上反映了每个边的重要性。例如,评论比喜欢更重要。 - 时间衰减(
d
)。故事越老,用户越不喜欢它。
那么 Facebook 如何通过这三个特征进行排名呢?计算算法非常简单。对于你创建的每个推文,将每条边的这些因子乘起来,然后将边的得分相加,就得到了更新的 EdgeRank。而且它越高,你的更新就越有可能出现在用户的推送中。
亲密度
我们可以做同样的事情来评估亲密度。
可以用各种因素来反映两个人的距离。首先,像评论,标签,分享,点击等显式交互是我们应该使用的强有力的信号。显然,每种类型的互动应该有不同的权重。例如,评论应该比喜欢多得多。
其次,还要跟踪时间因素。也许你曾经和一个好友进行过很多的交流,但最近还是比较少见。在这种情况下,我们应该降低亲密度。所以对于每一个互动,我们也应该考虑时间衰减因子。
作为排名部分的总结,我希望这个排名的常用方法可以成为你的收获。另外,EdgeRank 在 2010 年首次发布,可能已经过时了。
推送发布
当用户加载来自他的好友的所有推送时,这可能是开销很大的行为。请记住,用户可能有成千上万的好友,他们每个人都可以发布大量的更新,特别是对于高端用户。要加载来自好友的所有推文,系统至少需要两个连接(获取好友列表和推文列表)。
那么如何优化和扩展推送发布系统呢?
基本上有两种常见的方式 - 推和拉。
对于推送方式,一旦用户发布了一个推文,我们立即将这个推文(实际上是推文的指针)推送给他的所有好友。优点是在提取推文时,不需要浏览好友列表并获取来自每个好友的推文。它显着减少了读取操作。但是,缺点也是显而易见的。它增加了写操作,特别是对于有大量好友的人来说。
对于拉取方式,只有用户正在加载其主页时,才会提取推文。因此,推文数据在创建后不需要立即发送。你可以看到这种方法优化了写操作,但是即使在使用非规范化之后,获取数据也可能很慢(如果你不了解它,请查看我们之前的文章)。
这两种方法在某些情况下都能很好地工作,而且最好了解它们的优点和缺点。
选择性扇出(fanout)
将活动推给所有好友或粉丝的过程称为扇出。所以推送方式也被称为写时扇出,而拉入方式则是加载时扇出。
在这里,我想问问你是否有任何方法,来进一步优化扇出过程?
事实上,你可以将两者结合。具体而言,如果你主要使用推送方式,则可以做的是,禁用高级用户的扇出,而其他人只能在读取期间加载更新。这个想法是,推送操作对于高级用户来说可能开销很大,因为他们要通知很多好友。通过禁用他们的扇出,我们可以节省大量的资源。实际上 Twitter 采用这种方法后已经有了很大的改进。
同样的道理,一旦用户发布一个推文,我们也可以将扇出限制在他的活跃好友。对于非活跃用户,大多数时候推送操作是个浪费,因为他们将永远不会回来使用推送。
总结
如果遵循 80-20 规则,则 80% 的成本来自 20% 的功能/用户。因此,优化确实涉及瓶颈的确定。
此外,推送系统是一个非常受欢迎的话题,因为它现在被如此多的产品广泛使用。如果你对这个主题感兴趣,并想进一步探索,我建议你看看下面的资源: