LinkedIn 互联网架构扩展简史

LinkedIn成立于 2003 年,其目标是连接到您的网络以获得更好的工作机会。第一周只有 2,700 名会员。时间快进了很多年,LinkedIn 的产品组合、会员基础和服务器负载都取得了巨大的增长。

如今,LinkedIn 在全球运营,拥有超过 3.5 亿会员。我们每天每秒都会提供数以万计的网页。我们已经进入了移动时代,移动流量占全球流量的 50% 以上。所有这些请求都从我们的后端系统获取数据,而后端系统每秒处理数百万个查询。

那么,我们是如何到达那里的呢?

多年以前

就像今天许多网站一样,LinkedIn 最初是作为一个单一的整体应用程序完成这一切的。这个应用程序被称为 Leo。它托管所有不同页面的 Web servlet、处理业务逻辑并连接到一些 LinkedIn 数据库。

90e54f75584e23ccbdb876af79169eee.png
啊,网站开发的美好时光 - 美好而简单

成员图

作为社交网络要做的第一件事就是管理成员之间的连接。我们需要一个使用图形遍历查询连接数据并驻留在内存中的系统,以实现最高的效率和性能。由于这种不同的使用情况,很明显它需要独立于 Leo 进行扩展,因此我们的会员图表的一个名为 Cloud 的独立系统诞生了 - LinkedIn 的第一个服务。为了使该图服务与 Leo 分开,我们使用 Java RPC 进行通信。

大约在这个时候我们需要搜索功能。我们的会员图服务开始将数据输入到运行Lucene 的新搜索服务中。

副本读取数据库

随着网站的发展,Leo 也在不断发展,其角色和责任也不断增加,自然也增加了其复杂性。当多个 Leo 实例启动时,负载平衡很有帮助。但增加的负载给 LinkedIn 最关键的系统——其会员资料数据库带来了负担。

我们所做的一个简单的修复是经典的垂直扩展 - 投入更多的 CPU 和内存!虽然这赢得了一些时间,但我们需要进一步扩大规模。配置文件数据库同时处理读取和写入流量,因此为了扩展,引入了副本从属数据库。副本数据库是成员数据库的副本,使用最早版本的数据总线(现已开源)保持同步。它们被设置为处理所有读取流量,并构建逻辑来了解何时从副本读取相对于主主数据库是安全(一致)的。

aeed18058749276afa8482e711572572.png
* 虽然主从模型是中期解决方案,但我们已经转向分区数据库

随着网站的流量开始增加,我们的单一整体应用程序 Leo 经常在生产中出现故障,很难排除故障和恢复,也很难发布新代码。高可用性对于 LinkedIn 至关重要。很明显,我们需要“杀死 Leo”并将其分解为许多小型的功能性和无状态服务。

1db37c5c322a2a8137778af6d4116064.png
“杀死利奥”多年来一直是公司内部的口头禅……

面向服务的架构

工程部门开始提取微服务来保存 API 和业务逻辑,例如我们的搜索、个人资料、通信和群组平台。后来,我们的表示层被提取用于招聘人员产品或公共档案等领域。对于新产品,全新服务是在 Leo 之外创建的。随着时间的推移,每个功能区域都出现了垂直堆栈。

我们构建了前端服务器来从不同域获取数据模型、处理表示逻辑并构建 HTML(通过 JSP)。我们构建了中间层服务来提供对数据模型的 API 访问,并构建后端数据服务来提供对其数据库的一致访问。到 2010 年,我们已经拥有 150 多个独立服务。如今,我们拥有超过 750 项服务。

3537322fcbb43401b79c6f7d298fcf7e.png
LinkedIn 中面向服务的多层架构示例

由于无状态,可以通过启动任何服务的新实例并在它们之间使用硬件负载平衡器来实现扩展。我们积极开始对每个服务进行红线调整,以了解它可以承受多少负载,并构建了早期配置和性能监控功能。

缓存

LinkedIn 正在经历高速增长,需要进一步扩大规模。我们知道可以通过添加更多层缓存来完全减少负载。许多应用程序开始引入中间层缓存层,例如memcache或couchbase。我们还在数据层中添加了缓存,并在适当的时候开始使用带有预先计算结果的Voldemort。

随着时间的推移,我们实际上删除了许多中间层缓存。中间层缓存存储来自多个域的派生数据。虽然缓存一开始看起来是一种减少负载的简单方法,但失效和调用图的复杂性却变得失控。使缓存尽可能靠近数据存储可以保持较低的延迟,使我们能够水平扩展并减少认知负载。

Kafka

为了收集不断增长的数据量,LinkedIn 开发了许多用于流式传输和排队数据的自定义数据管道。例如,我们需要将数据流入数据仓库,我们需要将批量数据发送到我们的Hadoop 工作流程中进行分析,我们收集并聚合每个服务的日志,我们收集页面浏览量等跟踪事件,我们需要对 inMail 消息进行排队系统,每当有人更新个人资料时,我们都需要使我们的人员搜索系统保持最新状态。

随着网站的发展,更多的定制管道出现了。随着站点需要扩展,每个单独的管道也需要扩展。必须付出一些东西。结果是我们的分布式发布-订阅消息平台Kafka的开发。Kafka 成为一个通用管道,围绕提交日志的概念构建,并且在构建时考虑了速度和可扩展性。它使我们能够近乎实时地访问任何数据源,增强我们的 Hadoop 作业能力,使我们能够构建实时分析,极大地提高我们的站点监控和警报能力,并使我们能够可视化和跟踪我们的调用图。如今,Kafka每天处理超过5000 亿个事件。

9691b0c7ccc76d7b4f5e6bc20575fae4.png
Kafka 作为通用数据流代理

反转

规模化可以从多个维度来衡量,包括组织。2011 年底,LinkedIn 启动了一项名为Inversion的内部计划。这一举措暂停了功能开发,使整个工程组织能够专注于改进工具和部署、基础设施和开发人员的生产力。它成功地实现了我们构建当今可扩展新产品所需的工程敏捷性。

近代

当我们从 Leo 转型为面向服务的架构时,我们提取的 API 假设是基于 Java 的 RPC,跨团队不一致,与表示层紧密耦合,而且情况只会变得更糟。为了解决这个问题,我们构建了一个名为Rest.li的新 API 模型。Rest.li 是我们向以数据模型为中心的架构迈进的一步,它确保了整个公司一致的无状态 Restful API 模型。

通过使用 HTTP 上的 JSON,我们的新 API 最终使非基于 Java 的客户端变得容易。今天的 LinkedIn 仍然主要是一家 Java 商店,但也有许多使用 Python、Ruby、Node.js 和 C++ 的客户,这些都是内部开发的以及我们收购的技术堆栈。远离 RPC 还使我们摆脱了与表示层的高耦合和许多向后兼容性问题。另外,通过将动态发现 (D2)与 Rest.li 结合使用,我们获得了每个服务 API 的基于自动化客户端的负载平衡、发现和可扩展性。

如今,LinkedIn 在我们的所有数据中心拥有超过 975 个 Rest.li 资源,每天有超过 1000 亿次 Rest.li 调用。

421fd6b09cc3565f63e68549af32ea9a.png
Rest.li R2/D2 技术堆栈

超级积木

面向服务的架构可以很好地解耦域并独立扩展服务。但也有缺点。我们的许多应用程序获取多种类型的不同数据,进而进行数百个下游调用。在考虑所有许多下游调用时,这通常称为“调用图”或“扇出”。例如,任何个人资料页面请求获取的不仅仅是个人资料数据,还包括照片、连接、群组、订阅信息、关注信息、长篇博客文章、图表中的连接度、推荐等。此调用图可能难以管理并且变得越来越不守规矩。

我们引入了超级块的概念 - 具有单一访问 API 的后端服务分组。这使我们能够让特定的团队优化该块,同时检查每个客户端的调用图。

多数据中心

作为一家会员数量快速增长的跨国公司,我们需要扩大规模,超越从一个数据中心提供流量服务的范围。我们几年前就开始努力解决这个问题,首先是通过两个数据中心(洛杉矶和芝加哥)提供公共资料。一旦经过验证,我们就开始增强我们的所有服务,以处理数据复制、来自不同来源的回调、单向数据复制事件以及将用户固定到地理位置接近的数据中心。

我们的许多数据库都在Espresso(一种新的内部多租户数据存储)上运行。Espresso 在构建时就考虑到了多数据中心。它提供主/主支持并处理许多困难的复制。

多个数据中心对于维持“站点正常运行”和高可用性非常重要。您不仅需要避免每个单独服务的任何单点故障,还需要避免整个站点的任何单点故障。如今,LinkedIn 拥有三个主要数据中心,并在全球各地设有其他PoP 。

53bd1b63888368070f3f6741cd9b2464.png
LinkedIn 截至 2015 年的运营设置(圆圈代表数据中心,菱形代表 PoP)

我们还做了什么?

当然,我们的扩展故事从来没有这么简单。多年来,我们在所有工程和运营团队中做了无数的事情,其中包括一些更大的举措:

我们的许多最关键的系统都有自己丰富的历史和多年来解决规模问题的演变。这包括我们的会员图表服务(我们在 Leo 之外的第一项服务)、搜索(我们的第二项服务)、新闻源、通信平台和会员资料后端。

我们构建了能够实现长期增长的数据基础设施。这首先在 Databus 和 Kafka 中表现得很明显,然后在用于数据流的Samza 、用于存储解决方案的Espresso和 Voldemort、用于我们的分析系统的Pinot以及其他定制解决方案中得到延续。另外,我们的工具已经改进,开发人员可以自动配置此基础设施。

我们使用Hadoop和Voldemort 数据存储开发了一个大规模的离线工作流程,以预先计算数据见解,例如您可能认识的人、相似的个人资料、著名校友和个人资料浏览地图。

我们重新考虑了我们的前端方法,将客户端模板添加到组合中(个人资料页面、大学页面)。这使得应用程序的交互性更强,要求我们的服务器仅发送 JSON 或部分 JSON。另外,模板会缓存在 CDN 和浏览器中。我们还开始使用BigPipe和Play 框架,将我们的模型从线程 Web 服务器更改为非阻塞异步模型。

除了应用程序代码之外,我们还使用 Apache Traffic Server 和 HAProxy 引入了多层代理来处理负载平衡、数据中心固定、安全性、智能路由、服务器端渲染等。

最后,我们通过优化硬件、高级内存和系统调整以及利用更新的 Java 运行时,继续提高服务器的性能。

下一步是什么

LinkedIn 继续快速发展,我们仍有大量工作可以改进。我们正在解决很少有人能够解决的问题。


随手关注或者”在看“,诚挚感谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/289589.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

今日AI热点:科技前沿新动态

引言: 人工智能领域日新月异,每天都有令人振奋的新进展。从苹果到谷歌,从OpenAI到Meta,各大科技巨头纷纷推出创新产品和技术,不断推动着人工智能的发展。让我们一起来看看今日AI热点,探索这个充满活力和激情…

C++从入门到精通——命名空间

命名空间 前言一、命名空间引例什么是命名空间 二、命名空间定义正常的命名空间定义嵌套的命名空间多个相同名称的命名空间 三、命名空间使用加命名空间名称及作用域限定符使用using将命名空间中某个成员引入使用using namespace 命名空间名称引用引用命名空间和引用头文件有什…

Mac安装minio

Mac安装minio 本文介绍使用 mac 安装 MinIO。 所有软件安装优先参考官网:MinIO Object Storage for MacOS — MinIO Object Storage for MacOS #使用 brew 安装 minio brew install minio/stable/minio#找到 minio tong ~ $ brew list minio /opt/homebrew/Cella…

【ssh连接】奇奇怪怪报错记录

gitlab配置ssh连接,先跟着教程生成密钥,上传公钥,将服务器信息存入config文件,但是ssh连接超时,很急,想用服务器,各种搜索尝试,搞了两三天别的什么都没干,还是没解决&…

深度学习pytorch——激活函数损失函数(持续更新)

论生物神经元与神经网络中的神经元联系——为什么使用激活函数? 我们将生物体中的神经元与神经网络中的神经元共同分析。从下图可以看出神经网络中的神经元与生物体中的神经元有很多相似之处,由于只有刺激达到一定的程度人体才可以感受到刺激&#xff0c…

硬件6、AD设计PcbLib之引脚间如何设置距离及设置PCB元器件丝印

设置引脚间的距离 一个器件有两个引脚,在制作这个器件的pcblib时,需要设置两个引脚之间的距离 1、先选中其中一个引脚 2、然后拖动至两个引脚重叠 3、按下M键,通过X,Y移动选中对象 4、输入两个引脚中心点之间的距离 5、然后两…

【随笔】Git -- 基本概念和使用方式(五)

💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…

排序C++

题目 法1 sort升序排序&#xff0c;再逆序输出 #include<iostream> #include<algorithm> using namespace std;const int N 5e53;//注意const&#xff0c;全局 int a[N]; int main() {//错误int N5e53;//错误const int a[N];int n;cin >> n;for (int i 1;…

水电站生态流量监测解决方案:亲历水电站生态监控改造

​记得那是在2022年夏天,我所在的环保咨询公司接到了一项非常具有挑战性的监测项目。某省的环保部门要求对辖区内所有水电站的生态流量情况进行评估,并给出整改建议。作为项目负责人,我深知这项工作的重要意义。&#xff08;选自&#xff1a;智慧水务数字孪生安全监测解决方案提…

正式发布:VitePress 1.0 现代化静态站点生成器!

大家好&#xff0c;我是奇兵&#xff0c;今天介绍一下现代化静态站点生成器!&#xff0c;希望能帮到大家。 3 月 21 日&#xff0c; 由 Vue 团队出品的现代化静态站点生成器 VitePress 正式发布 1.0 版本&#xff01;它专为构建快速、以内容为中心的网站而生&#xff0c;能够轻…

Wagtail-基于Python Django的内容管理系统CMS实现公网访问

目录 前言 1. 安装并运行Wagtail 1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具 3. 实现Wagtail公网访问 4. 固定Wagtail公网地址 前言 Wagtail是一个用Python编写的开源CMS&#xff0c;建立在Django Web框架上。Wagtail 是一个基于 Django 的开源内容管理系统&…

python知识点总结(十)

python知识点总结十 1、装饰器的理解、并实现一个计时器记录执行性能&#xff0c;并且将执行结果写入日志文件中2、队列和栈的区别&#xff0c;并且用python实现3、设计实现遍历目录与子目录4、CPU处理进程最慢的情况通常发生在以下几种情况下&#xff1a;5、CPU处理线程最慢的…

计算机网络基础——网络安全/ 网络通信介质

chapter3 网络安全与管理 1. 网络安全威胁 网络安全&#xff1a;目的就是要让网络入侵者进不了网络系统&#xff0c;及时强行攻入网络&#xff0c;也拿不走信息&#xff0c;改不了数据&#xff0c;看不懂信息。 事发后能审查追踪到破坏者&#xff0c;让破坏者跑不掉。 网络…

c++核心学习--继承2

4.6.7多继承语法 4.6.8菱形继承 利用虚继承解决菱形继承的问题&#xff1a;继承之前加上关键字virtual变为虚继承

基于随机森林与LSTM神经网络的住宅用电比较分析及预测 代码+论文 完整毕设

摘要 本文旨在探讨基于随机森林&#xff08;Random Forest&#xff09;与长短期记忆神经网络&#xff08;Long Short-Term Memory, LSTM&#xff09;的住宅用电比较分析及预测方法。随机森林是一种集成学习方法&#xff0c;通过构建多个决策树进行预测&#xff0c;具有较强的鲁…

【每日一题】2024年3月汇编(上)

3.1【2369】检查数组是否存在有效划分 2369. 检查数组是否存在有效划分https://leetcode.cn/problems/check-if-there-is-a-valid-partition-for-the-array/ 1.这样的判断可以用动态规划来解决&#xff0c;用一个长度为(n1) 的数组来记录 是否存在有效划分&#xff0c;dp[i]…

前端学习笔记 | Node.js

一、Node.js入门 1、什么是Node.js 定义&#xff1a;是跨平台JS运行环境&#xff08;可以独立执行JS的环境&#xff09;作用&#xff1a; 编写数据接口&#xff0c;提供网页资源功能等等前端工程化&#xff1a;为后续学Vue和React等框架做铺垫 2、Node.js为何能执行JS&#xff…

思维升级之路:观察思维深层,解锁认知新境界

目录 一、观察我们的思维习惯 二、人类有哪些思维方法 三、为什么要多使用归纳推理而不是演绎推理 四、转变思维的关键 - 觉察 怎么提升自身的认知水平&#xff1f;这篇文章里&#xff0c;作者尝试对思维模式这件事做出探讨&#xff0c;一起来看看&#xff0c;或许可以帮你…

JUC内容概述

复习概念 Sleep和Wait的区别 Sleep是Thread的静态方法&#xff0c;wait是Object的方法&#xff0c;任何对象实例都可以使用sleep不会释放锁&#xff0c;他也不需要占用锁&#xff0c;暂停。wait会释放锁&#xff0c;但是调用他的前提是线程占有锁他们都可以被Interrupted方法…

Gartner 公布 2024 年八大网络安全预测

近日&#xff0c;Gartner 安全与风险管理峰会在悉尼举行&#xff0c;旨在探讨网络安全的发展前景。 本次峰会&#xff0c;Gartner 公布了 2024 年及以后的八大网络安全预测。 Gartner 研究总监 Deepti Gopal 表示&#xff0c;随着 GenAI 的不断发展&#xff0c;一些长期困扰网…