在过去的二十年中,大规模的在线应用程序已经取得了长足的进步。 这些创新改变了我们对软件开发的看法。 例如,Facebook、Instagram 和 Twitter 都是可扩展的平台。
必须构建这些系统来管理大量流量和数据,因为全世界有数十亿人同时使用它们。 这是当 系统设计 进入图片。
为满足特定标准的系统建立体系结构、接口和数据的过程称为系统设计。 通过有凝聚力和高效的系统,系统设计可以满足您的业务或组织的需求。
一旦您的公司或组织确定了其标准,您就可以开始将它们整合到满足消费者需求的物理系统设计中。
无论您选择定制开发、商业解决方案还是两者的结合,您如何设计系统将决定您如何构建它。
我们将在这篇文章中详细介绍 Twitter 时间线的系统设计,并附上教程。 让我们开始吧。
第 1 步:概述用例和约束
用例
- 用户上传推文。
- 该服务向推文的关注者发送推送通知和电子邮件。
- 查看用户的时间线(来自用户的活动)
- 用户查看主页时间线(用户关注的人的活动)
- 关键字由用户搜索。
- 该服务真的很容易获得。
超出范围
- 使用此服务将推文发送到 Twitter Firehose 和其他流。
- 该服务根据用户的可见性设置删除推文。
- 如果用户没有关注被回复的人,请隐藏回复。
- 观察“隐藏转发”选项。
- 数据分析
约束和假设
状态假设
- 流量分布不均。
- 发送推文应该很简单。
- 除非您拥有数百万关注者,否则向所有关注者发送推文应该很快。
- 有100亿活跃用户。
- 每月 15 亿条推文或每天 500 亿条推文
- 每条推文平均有 10 次分发。
- 每天,fanout 会发布 5 亿条推文。
- Fanout 每月发布 150 亿条推文。
- 每月 250 亿次读取请求
- 每月 10 亿次搜索
时间线
- 时间线应该易于浏览。
- Twitter 更多的是阅读而不是写作。
- 优化快速阅读推文
- 推文消费很耗时。
搜索
- 搜索过程应该很快。
- 搜索很费时间。
计算用量
每条推文的大小:
- 8 字节推文 ID
- 32 字节的用户 ID
- 140 字节的文本
- 媒体 – 平均 10 KB
- 总计:~10 KB
每个月都会生成 150 TB 的新推文内容。
- * 每天 500 亿条推文 * 每月 30 天 * 每条推文 10 KB
- 三年内,有 5.4 PB 的新鲜推文内容。
每秒有 100,000 个读取请求。
- *(每秒 400 次请求 / 每月 1 亿次请求)每月 250 亿次读取请求
每秒有 6,000 条推文。
- *(每秒 400 次请求 / 每月 1 亿次请求)每月 15 亿条推文
在扇出时,每秒发送 60 万条推文。
- Fanout 每月发送 150 亿条推文*(每秒 400 个请求/每月 1 亿个请求)。
每秒 4,000 个信息请求
- *(每秒 400 次请求 / 每月 1 亿次请求)每月 10 亿次搜索
一些有用的转换
- 每个月,2.5 万秒过去了。
- 每月 2.5 万个请求,每秒 1 个请求
- 每月 100 亿次请求 x 每秒 40 次请求
- 每月 1 亿个请求 = 每秒 400 个请求
第 2 步:高级图表
第 3 步:解释核心组件
如果用户提交了推文,我们可以保存用户自己的推文,以便在关系数据库中填充用户时间线(来自用户的活动)。 发布推文和开发主页时间线(用户关注的个人的活动)更加困难。
典型的关系数据库会因向所有关注者发送推文(每秒发送 60 万条推文)而不堪重负。 我们可能想要使用像 NoSQL 数据库或内存缓存这样的快速写入数据存储。
从内存中顺序读取 1 MB 大约需要 250 微秒,但从 SSD 读取需要 4 倍的时间,从磁盘读取需要 80 倍的时间。
对象存储可用于存储图像和视频等数据。
- 充当反向代理的 Web 服务器接收来自客户端的推文。
- 请求由 Web 服务器发送到 Write API 服务器。
- Write API 将推文保存到用户时间线中的 SQL 数据库中。
写入 API 联系扇出服务,它执行以下任务。
- 通过查询用户图服务在内存缓存中找到用户的关注者。
- 在内存缓存上,推文保存在用户关注者的主页时间线中。
- 1,000 个关注者 = 1,000 次查找和插入 = O(n) 操作。
- 推文保存在搜索索引服务中,以便快速搜索。
- 对象存储用于存储媒体。
- 通过通知服务向关注者发送推送警报。
- 要异步发送警报,它使用队列。
如果我们的内存缓存是 Redis,我们可以使用具有以下结构的本机 Redis 列表:
用户的主页时间线将使用新推文进行更新,该推文将存储在内存缓存中。 我们将使用以下公共 REST API:
用户时间线由用户查看。
- Web 服务器接收来自客户端的用户时间线请求。
- 请求由 Web 服务器发送到读取 API 服务器。
- 读取 API 查询 SQL 数据库以获取用户时间范围。
REST API 的工作方式与主时间线类似,但所有推文都来自用户而不是他们关注的人。
用户搜索关键字:
- Web 服务器收到来自客户端的搜索请求。
- 请求由 Web 服务器发送到 Search API 服务器。
第 4 步:推特时间线
创建时间线是一项艰巨的任务。 需要一个链接到 Web 或应用程序服务器的时间线生成服务器。
每次用户登录时,时间线服务都会跟踪关注者表中用户的最新推文,并更新或刷新用户的时间线。
我们在这里没有实施任何排序系统; 相反,我们假设来自用户关注者的前 5 条推文按照创建时间的顺序显示在时间轴中。 我们可以保持 50 条推文刷新截止。 在达到该阈值后,我们仍然会停止刷新或构建时间线,直到用户刷新页面。
高延迟和性能问题将来自实时用户提要创建。 相反,创建可以立即呈现的离线流是提高性能的最佳方式。 运行定期 ping 应用程序服务器的专用时间线服务器,以根据创建时间刷新提要。
排名算法应考虑关键信号并提供权重,以确保用户的时间线不会被他们关注的一个或多个帐户的材料支配。
更准确地说,我们可以选择与任何提要项的相关性相关的特征,例如喜欢的数量、评论、分享和更新时间。 这些标准中的每一个都应该用于对推文进行评级,然后应该使用该排名来在时间轴上显示推文。
我们是否应该在他们的新闻源有新内容可用时不断提醒用户? 用户会发现在有新数据可用时收到警报是有益的。 然而,在移动设备上,当数据使用成本很高时,它会浪费带宽。
因此,我们可以选择不将数据推送到移动设备,而是允许用户“拉动刷新”以获取新帖子。
第 5 步:缩放设计
一个潜在的瓶颈是扇出服务。 拥有数百万粉丝的 Twitter 用户将不得不等待几分钟才能发布他们的推文。 这可能会导致对推文的回复竞争,我们可以通过在服务时重新排序推文来避免这种情况。
我们还可以防止从拥有大量关注者的人那里传播推文。 相反,我们可能会搜索来自高度关注的个人的推文,将搜索结果与用户的主页时间线结果整合,然后在服务时重新排序推文。
其他增强功能包括:
- 每个家庭时间线的内存缓存中只保留几百条推文。
- 在内存缓存中,仅保存活动用户的主页时间线信息。
- 如果用户在前 30 天内没有活动,我们可以从 SQL 数据库重建年表。
- 要找出用户是谁,请使用用户图服务。
- 通过从 SQL 数据库中检索推文,将推文添加到内存缓存中。
- Tweet Info Service 只能保存一个月的推文。
- 在用户信息服务中,仅保存活动用户。
- 为了保持低延迟,搜索集群很可能需要在内存中维护推文。
结论
虽然 Twitter 是一个大型组织,但它有更好的 对系统设计的理解. 我尽力为您提供 Twitter 时间线的高级概述。
我希望您从中获得有用的信息,并能很好地利用它。
发表评论