当前位置: 首页 > news >正文

系统架构不是设计出来的

今天给大家分享一个 X/ Twitter 早期系统架构演变的故事,内容来自《数据密集型应用系统设计》这本书,具体数据来自 X/ Twitter 在 2012 年 11 月发布的分享。

推特的两个主要业务是:

  • 发布推文(Tweets)。用户可以向其粉丝发布新消息(平均 4.6k 请求 / 秒,峰值超过 12k 请求 / 秒)。

  • 主页时间线(Timeline)。用户可以查阅他们关注的人发布的推文(300k 请求 / 秒)。

仅仅处理峰值每秒 12000 次写入还是很简单的,然而推特的扩展性挑战并不是主要来自推特量,而是来自扇出(fan-out)- 每个用户关注了很多人,也被很多人关注。

扇出:从电子工程学中借用的术语,它描述了输入连接到另一个门输出的逻辑门数量。 输出需要提供足够的电流来驱动所有连接的输入。在事务处理系统中,我们使用它来描述为了服务一个传入请求而需要执行其他服务的请求数量。

大体上讲,这一操作有两种实现方式。

方法一:发布推文时,只需将新推文插入全局推文集合即可。当一个用户请求自己的主页时间线时,首先查找他关注的所有人,查询这些被关注用户发布的推文并按时间顺序合并。在下图所示的关系型数据库中,可以编写这样的查询:

SELECT tweets.*, users.*FROM tweetsJOIN users   ON tweets.sender_id = users.idJOIN follows ON follows.followee_id = users.idWHERE follows.follower_id = current_user

推特主页时间线的关系型模式简单实现
X/ Twitter 的第一个版本使用了方法一,但是随着用户的增长,系统很难跟上主页时间线查询的负载(300k 请求 / 秒)。

方法二:为了应对高查询负载,为每个用户的主页时间线维护一个缓存,就像每个用户的推文收件箱,如下图所示。

用于分发推特至关注者的数据流水线
当一个用户发布推文时,查找所有关注该用户的人,并将新的推文插入到每个主页时间线缓存中。 因此读取主页时间线的请求开销很小,因为结果已经提前计算好了。

X/ Twitter 公司转向了方法二之后的效果更好,因为发推频率比查询主页时间线的频率几乎低了两个数量级,所以在这种情况下,最好在写入时做更多的工作,而在读取时做更少的工作。

然而方法二的缺点是发推文现在需要大量的额外工作。平均来说,一条推文会发往约 75 个关注者,所以每秒 4.6k 的发推写入,变成了对主页时间线缓存每秒 345k 的写入。而且这个平均值隐藏了用户粉丝数差异巨大这一现实,一些用户有超过 3000 万的粉丝,这意味着一条推文就可能会导致主页时间线缓存的 3000 万次写入!及时完成这种操作是一个巨大的挑战,推特尝试在 5 秒内向粉丝发送推文。

在推特的例子中,每个用户粉丝数的分布(可能按这些用户的发推频率来加权)是探讨可伸缩性的一个关键负载参数,因为它决定了扇出负载。其他应用程序可能具有非常不同的特征,但可以采用相似的原则来考虑它的负载。

X/ Twitter 轶事的最终转折:现在已经稳健地实现了方法二,推特逐步转向了两种方法的混合。大多数用户发的推文会被扇出写入其粉丝主页时间线缓存中。但是少数拥有海量粉丝的用户(即名流)会被排除在外。当用户读取主页时间线时,分别地获取出该用户所关注的每位名流的推文,再与用户的主页时间线缓存合并,如方法一所示。这种混合方法能始终如一地提供良好性能。

总结

系统架构具有复杂性和动态性,需要随着业务需求、技术革新等外部环境变化而不断调整和完善,而非仅仅通过预先设计就能够达到最优状态。推荐大家阅读《数据密集型应用系统》这本书,它可以帮助我们了解如何设计、构建和维护可靠、可扩展且易于维护的数据密集型应用系统。

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 华为OD机试-周末爬山(JavaPythonC++)100%通过率,最新E卷题目
  • 【Oracle点滴积累】解决ORA-29913和KUP-04095: preprocessor command的方法
  • DBSCAN算法及Python实践
  • 2.pandas--读取文件夹中所有excel文件进行合并
  • 芯片后端之 PT 使用 report_timing 产生报告 之 -input_pins 选项
  • Linux编程: C++程序线程CPU使用率监控与分析小工具
  • 企业高性能web服务器(nginx)
  • 【TB作品】PIC16F1719单片机,EEPROM,PFM,读写,PIC16F1718/19
  • ST-LINK常见错误总结
  • 实现MySQL的主从复制基础
  • 如何保证Redis与数据库之间的一致性
  • C/C++ 线程局部存储(TLS)
  • vue3+vite配置环境变量实现开发、测试、生产的区分
  • 利用Matlab求解常微分方程(dsolve与ode45)
  • easypoi模板导出word并且合并行
  • [PHP内核探索]PHP中的哈希表
  • DOM的那些事
  • gf框架之分页模块(五) - 自定义分页
  • Redis字符串类型内部编码剖析
  • REST架构的思考
  • Spring核心 Bean的高级装配
  • SQLServer插入数据
  • vue的全局变量和全局拦截请求器
  • Vultr 教程目录
  • 成为一名优秀的Developer的书单
  • 浮动相关
  • 计算机在识别图像时“看到”了什么?
  • 技术:超级实用的电脑小技巧
  • 来,膜拜下android roadmap,强大的执行力
  • 区块链技术特点之去中心化特性
  • 使用 @font-face
  • 使用 QuickBI 搭建酷炫可视化分析
  • 使用parted解决大于2T的磁盘分区
  • 手写双向链表LinkedList的几个常用功能
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 阿里云ACE认证之理解CDN技术
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​你们这样子,耽误我的工作进度怎么办?
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • (1)无线电失控保护(二)
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (4)事件处理——(7)简单事件(Simple events)
  • (Java数据结构)ArrayList
  • (多级缓存)多级缓存
  • (分布式缓存)Redis持久化
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (理论篇)httpmoudle和httphandler一览
  • (一)、软硬件全开源智能手表,与手机互联,标配多表盘,功能丰富(ZSWatch-Zephyr)
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献