Skip to content

十一、设计新闻订阅系统

在这一章中,你被要求设计一个新闻订阅系统。什么是新闻订阅源?根据脸书的帮助页面,“新闻提要是在你的主页中间不断更新的故事列表。新闻源包括状态更新、照片、视频、链接、应用活动 、 ,以及你在脸书上关注的人、页面和群组的赞。这是一个常见的面试问题。常见的类似问题有:设计脸书新闻提要、Instagram 提要、Twitter 时间线等。

A screenshot of a cell phone  Description automatically generated

第一步——了解问题并确定设计范围

第一组澄清性问题是当面试官让你设计一个新闻反馈系统时,你要明白她在想什么。至少,您应该弄清楚要支持哪些特性。下面是一个应聘者与面试官互动的例子:

考生 :这是手机 app 吗?还是一个 web app?还是两者都有?

面试官 :双方

候选人 :有哪些重要特征?

采访: 用户可以发表帖子,并在新闻订阅页面上看到她朋友的帖子。

候选人 : 新闻提要是按时间倒序排序还是按话题分数等任何特定顺序排序?例如,来自你亲密朋友的帖子得分更高。

面试官 : 为了简单起见,我们假设提要是按时间倒序排序的。

候选人 : 一个用户可以有多少好友?

面试官 : 5000

候选人 :车流量是多少?

面试官:1000 万 DAU

候选:feed 可以包含图片、视频,或者只是文字?

面试官 :可以包含媒体文件,包括图片和视频。

现在你已经收集了需求,我们集中精力设计系统。

第二步——提出高水平的设计并获得认同

设计分为两个流程:feed 发布和新闻 feed 构建。

Feed 发布:当用户发布帖子时,相应的数据被写入缓存和数据库。她朋友的新闻订阅源上有一个帖子。

新闻提要构建:为了简单起见,我们假设新闻提要是通过按时间倒序聚合朋友的帖子构建的。

新闻源 API

新闻提要 API 是客户端与服务器通信的主要方式。这些 API 是基于 HTTP 的,允许客户端执行操作,包括发布状态、检索新闻提要、添加好友等。我们讨论两个最重要的 API:提要发布 API 和新闻提要检索 API。

Feed 发布 API

要发布帖子,将向服务器发送 HTTP POST 请求。API 如下所示:

后/v1/me/进给

参数:

内容:内容是帖子的正文。

auth _ token:用于认证 API 请求。

新闻订阅源检索 API

检索新闻提要的 API 如下所示:

GET /v1/me/feed

参数:

auth _ token:用于认证 API 请求。

饲料出版

图 11-2 显示了提要发布流程的高层设计。

A close up of a map  Description automatically generated

用户:用户可以在浏览器或移动应用程序上查看新闻源。一个用户通过 API 发布了一个内容为“你好”的帖子:

/v1/me/feed?内容=你好&认证令牌= {认证令牌}

负载均衡器:将流量分配给 web 服务器。

Web 服务器:Web 服务器将流量重定向到不同的内部服务。

Post 服务:在数据库和缓存中持久保存帖子。

Fanout 服务:向好友的新闻推送新内容。新闻订阅源数据存储在缓存中,以便快速检索。

通知服务:通知好友有新内容,发送推送通知。

新闻大楼

在本节中,我们将讨论新闻提要是如何在幕后构建的。图 11-3 显示了高层设计:

A close up of a logo  Description automatically generated

用户:用户发送请求来检索她的新闻提要。请求看起来是这样的: / v1/me/feed。

负载平衡器:负载平衡器将流量重定向到 web 服务器。

Web 服务器:Web 服务器将请求路由到新闻订阅服务。

新闻订阅服务:新闻订阅服务从缓存中获取新闻订阅。

新闻提要缓存:存储呈现新闻提要所需的新闻提要 id。

第三步——设计深潜

概要设计简要地涵盖了两个流程:提要发布和新闻提要构建。在这里,我们更深入地讨论这些话题。

供稿出版深潜

图 11-4 概述了 feed 发布的详细设计。我们已经讨论了高层设计中的大部分组件,我们将集中讨论两个组件:web 服务器和扇出服务。

A close up of a map  Description automatically generated

网络服务器

除了与客户端通信之外,web 服务器还执行身份验证和速率限制。只有使用有效 auth_token 登录的用户才可以发帖。该系统限制用户在一定时间内可以发布的帖子数量,这对防止垃圾邮件和滥用内容至关重要。

扇出服务

扇出是向所有朋友发送帖子的过程。两种类型的扇出模型是:写时扇出(也称为推模型)和读时扇出(也称为拉模型)。两种模式各有利弊。我们解释他们的工作流程,并探索支持我们系统的最佳方法。

写时扇出。 用这种方法, 新闻提要是在编写时间内预先计算好的。新帖子发布后会立即发送到朋友的缓存中。

优点:

新闻提要实时生成,可以立即推送给朋友。

获取新闻提要的速度很快,因为新闻提要是在编写时预先计算的。

缺点:

如果一个用户有很多朋友,那么获取他们的好友列表并为他们生成新闻提要会非常缓慢和耗时。叫做热键问题。

对于不活跃的用户或者很少登录的用户来说,预先计算的新闻提要浪费了计算资源。

扇出上读 。新闻提要是在读取时生成的。这是一种随需应变的模式。当用户加载她的主页时,最近的帖子被拉出来。

优点:

对于不活跃的用户或者那些很少登录的用户来说,read 上的 fanout 工作得更好,因为它不会在他们身上浪费计算资源。

数据不会推送给朋友,所以不存在热键问题。

缺点:

获取新闻提要很慢,因为新闻提要不是预先计算的。

我们采用了一种混合方法,以获得两种方法的优点并避免其中的缺陷。因为快速获取新闻提要至关重要,所以我们对大多数用户使用推送模型。对于有很多朋友/关注者的名人或用户,我们让关注者按需拉新闻内容,以避免系统过载。一致哈希是一种缓解热键问题的有用技术,因为它有助于更均匀地分布请求/数据。

让我们仔细看看扇出服务,如图 11-5 所示。

A close up of a map  Description automatically generated

扇出服务的工作方式如下:

1。从图形数据库中获取朋友 id。图形数据库适合于管理朋友关系和朋友推荐。有兴趣的读者希望了解更多关于这个概念的信息,可以参考参考资料[2]。

2。从用户缓存中获取朋友信息。然后,系统会根据用户设置过滤掉朋友。例如,如果你将某人设为静音,即使你们仍然是朋友,她的帖子也不会显示在你的新闻订阅源上。帖子可能不会显示的另一个原因是,用户可以有选择地与特定的朋友分享信息,或者对其他人隐藏信息。

3。将好友列表和新帖子 ID 发送到消息队列。

4。扇出工作器从消息队列获取数据,并将新闻提要数据存储在新闻提要缓存中。你可以把新闻提要缓存想象成一个 < post_id,user_id > 的映射表。每当一个新的文章发表,它将被附加到新闻提要表中,如图 11-6 所示。如果我们将整个用户和 post 对象存储在缓存中,内存消耗会变得非常大。因此,只存储 id。为了保持较小的内存大小,我们设置了一个可配置的限制。用户在新闻订阅中滚动浏览数千条帖子的可能性很小。大部分用户只对最新的内容感兴趣,所以缓存缺失率很低。

5。在新闻提要缓存中存储 <帖子 id,用户 id > 。图 11-6 显示了新闻提要在缓存中的样子。

A screenshot of a cell phone  Description automatically generated

新闻提要检索深度剖析

图 11-7 展示了新闻提要检索的详细设计。

A close up of a map  Description automatically generated

如图 11-7 所示,媒体内容(图片、视频等。)存储在 CDN 中,以便快速检索。让我们看看客户机如何检索新闻提要。

1。用户发送请求来检索她的新闻提要。请求看起来是这样的: /v1/me/feed

2。负载平衡器将请求重新分配给 web 服务器。

3。Web 服务器调用新闻提要服务来获取新闻提要。

4。新闻提要服务从新闻提要缓存中获取一个帖子 id 列表。

5。用户的新闻提要不仅仅是一个提要 id 列表。它包含用户名,个人资料图片,帖子内容,帖子图片等。因此,新闻提要服务从缓存(用户缓存和帖子缓存)中获取完整的用户和帖子对象,以构建完整的新闻提要。

6。完整的新闻提要以 JSON 格式返回给客户端进行呈现。

高速缓存架构

对于新闻订阅系统来说,缓存非常重要。我们将缓存层分为 5 层,如图 11-8 所示。

A picture containing screenshot  Description automatically generated

新闻提要:存储新闻提要的 id。

内容:存储每条帖子的数据。热门内容存储在热缓存中。

社交图:存储用户关系数据。

动作:它存储了用户是否喜欢某个帖子、回复某个帖子或对某个帖子采取其他动作的信息。

计数器:存储点赞、回复、关注者、关注等计数器。

步骤 4 -总结

在这一章中,我们设计了一个新闻订阅系统。我们的设计包含两个流程:提要发布和新闻提要检索。

和任何系统设计面试问题一样,设计一个系统没有完美的方法。每个公司都有其独特的限制,你必须设计一个系统来适应这些限制。理解设计和技术选择的权衡非常重要。如果还有几分钟,可以谈谈可伸缩性问题。为了避免重复讨论,下面只列出了高层次的话题。

缩放数据库:

垂直缩放与水平缩放

T2】SQL vs NoSQL

主从复制

读取副本

一致性模型

T2】数据库分片

其他谈话要点:

保持 web 层无状态

尽可能多地缓存数据

支持多个数据中心

丢失消息队列的几个组件

监控关键指标。例如,用户刷新新闻提要时的高峰时间和延迟时间的 QPS 值得关注。

祝贺你走到这一步!现在给自己一个鼓励。干得好!

参考资料

[1]新闻订阅的工作原理:

https://www.facebook.com/help/327131014036297/

【2】朋友的朋友推荐 Neo4j 和 SQL Sever:

http://geekswithblogs . net/brendon page/archive/2015/10/26/friend-of-friend-of-friend-recommendations-with-neo4j . aspxT3】



回到顶部