原文: http://colobu.com/2015/07/24/brief-history-scaling-linkedin/

原文: A Brief History of Scaling LinkedIn

Josh Clemm是LinkedIn的高级工程经理,自2011年加入LinkedIn。他最近(2015/07/20)写了一篇文章,介绍了LinkedIn针对用户规模急速扩大带来的架构方面的变革。
文章有点像子柳写的淘宝技术这十年

2003年是LinkedIn元年,成立的目标是连接你个人人脉以获得更好的的工作机会。上线第一周才有2700个会员注册,时光飞梭,LinkedIn的产品、会员数量、服务器负载都极大的增长了。
今天,LinkedIn全球用户已经超过3.5亿。我们每秒有数十万个页面被访问,移动端流量已占到50%以上 (mobile moment)。所有这些请求都从后台获取数据,而我们的后台系统可以处理每秒上百万次查询。

问题来了: 所有这些是怎么做到的呢?

早期

Leo

和现在很多站点开始的时候一样, LinkedIn使用一个应用程序做所有的工作。 这个应用程序被称之为 "Leo"。它包含所有的Java Servlet页面, 处理业务逻辑, 连接少量的LinkedIn数据库。

哈!早年网站的样式-简单实用

Member Graph (会员关系图)

开始做的工作之一就是管理会员之间的关系的社交网络。我们需要一个系统通过图遍历(graph traversals)的方式来查询关系数据, 同时需要将数据驻留内存以便获得高效和性能。从这个不同的使用特征来看, 很明显这需要一个独立于Leo的系统以方便扩大规模,于是一个叫做"Clould"专门用于会员关系图(member graph)的独立系统诞生了。这是LinkedIn的第一个服务系统。为了和Leo系统分离,我们使用Java RPC来进行通讯。

也大约在此期间我们需要增加搜索服务的能力。我们的会员关系图服务也提供数据给一个基于Lucene的搜索服务。

Replica read DBs (多个只读数据库副本)

随着站点的增长, Leo系统也在扩大, 增加了更多的角色和职能, 也更加的复杂。 通过负载均衡可以运行多个Leo实例,但是新增的负载也影响到LinkedIn的最关键系统-会员信息数据库。

一个最容易的解决方案就是垂直扩展 - 在其上增加更多的CPU和内存。这虽然可以支撑一段时间,当将来我们还是会遇到规模扩展的问题。会员信息数据库既处理读又处理写。 为了扩展,我们引入了复制从库(replica slave DB)。 复制数据库是会员数据库的一个拷贝, 使用 databus (现已开源)的最早的版本来进行同步。这些复制从库处理所有的读请求, 并且增加了保证主库和从库数据一致性的逻辑。


主从读写分离的方案之后,我们转向了数据库分区的解决方案

当站点遇到越来越多的流量时,单一的Leo系统经常宕机,而且很难排查和恢复, 发布新代码也很困难。 高可用性对LinkedIn至关重要, 很明显我们需要"干掉" Leo, 把它分解成多个小的功能模块和无状态的服务。

"Kill Leo"这个咒语在内部传颂了好多年

Service Oriented Architecture (面向服务的架构)

工程师开始抽取出一些微服务, 这些微服务提供API和一些业务逻辑, 如搜索,会员信息, 通讯和群组平台。接着我们的表现层也抽取出来了,比如招聘产品和公共信息页。新产品,新服务都独立于Leo。 不久,各个功能区的垂直栈完成了。
我们构建了前端服务器, 可以从不同的域获取数据,处理展示逻辑以及生成HTML (通过JSP)。我们还构建了中间层服务提供API接口访问数据模型以及提供数据库一致性访问后端数据服务。到2010年,我们已经有超过150个独立的服务,而今天,我们已经有超过750个服务。

因为无状态, 规模扩展可以通过堆叠任意服务的新实例以及在它们之间进行负载均衡来完成。我们给每个服务设定了警戒红线, 知道它的负载能力, 提供早期预警和性能监控。

cache (缓存)

LinkedIn可预见的增长促使我们进一步的扩展。我们知道通过添加更多的缓存层以减少负载压力。很多应用开始引入中间缓存层如 memecached 或者 couchbase。 我们还在数据层增加了缓存, 并且在适当的时候使用 Voldemort 提供预先计算的结果。

之后,我们实际上去掉了中间缓存层。中间缓存层存储来自多个域的数据。虽然开始时缓存看起来是减少压力的一种简单的方式,但是缓存数据失效的复杂性和调用图(call graph)变得无法控制。将缓存更可能地接近数据层可以降低延迟, 使我们可以水平扩展,降低可知的负载(cognitive load)。

Kafka

为了收集日益增长的数据,LinkedIn开发了很多定制的数据通道来流水化和队列化数据(streaming and queueing)。 比如, 我们需要将数据放入数据仓库,我们需要将一批数据放入Hadoop工作流以便分析,我们从每个服务中中聚合了大量日志, 我们收集了很多用户追踪事件如页面点击, 我们需要队列化inMail消息系统中的数据, 我们需要保证用户更新完个人信息后搜索数据也是最新的等等。
随着网站还在壮大,更多的定制的管道出现了。 因为网站规模需要扩展,每一个独立的管道也需要扩展, 有些东西不得不放弃。 结果就是Kafka的开发, 我们的分布式的发布订阅消息系统。Kafka成为一个同一的管道, 根据commit log的概念构建, 特别注重速度和扩展性。 它可以接近实时的访问数据源,驱动Hadoop任务, 允许我们否件实时的分析,广泛地提升了我们的站点监控和报警能力, 也使我们能够可视化和跟踪调用图(call graph)。 今天, Kafka
每天处理超过5千亿的事件。

Inversion(反转)

扩展可以从很多维度来衡量,包括组织结构。 在2011年底, LinkedIn开始了一个内部创新,叫 “反转” (Inversion)。我们暂停了新功能的开发, 允许整个工程部门专注于提升工具,部署,基础架构和开发者生产力上。它成功地使我们可以敏捷地建立可扩展性新产品。

近几年

Rest.li

当我们从Leao转向面向服务的架构后,之前抽取的基于Java RPC的API, 在团队中开始变得不一致了,和表现层耦合太紧,这只会变得更糟。为了解决这个问题, 我们开发了一个新的API模型,叫做 Rest.li. Rest.li 符合我们面向数据模型的架构, 确保在整个公司提供一致性的无状态的Restful API模型。
基于HTTP的JSON数据, 我们新的API最终很容易地编写非Java的客户端。 LinkedIn今天仍然主要使用Java栈,但是也有很多使用Python, Ruby, Node.js, 和 C++的客户端,可能是在家开发的或者收购过来的。 脱离了RPC也让我们将变现层和后端兼容型的问题中挣脱出来。另外, 使用Dynamic Discovery (D2)的Rest.li, 我们可以得到自动的基于负载均衡,服务发现和可扩展的API客户端。
今天, LinkedIn有975 个Rest.li资源, 所有的数据中心每天有超过一千亿级Rest.li调用。
Rest.li R2/D2 技术站

Super Blocks (超级块)

面向服务的架构很好的解耦了域之间的联系和可以独立地扩展服务。但是也有缺点, 很多应用获取各种类型的不同的数据, f(call graph)或者叫做"扇出" (fanout)。例如, 任意一次个人信息页的请求就会获取照片,会员关系, 组,订阅信息, 关注,博客,人脉,推荐等信息。 这个调用图河南管理,而且越来越难控制。
我们引入了超级块的概念。 为一组后台服务提供一个单一的访问API。这样我们就可以有一个team专门优化这个块,同时保证每个客户端的调用图可控。

Multi-Data Center (多数据中心)

作为一个会员快速增长的全球化公司,我们需要从一个数据中心进行扩展,我们努力了几年来解决这个问题,首先,从两个数据中心(洛杉矶 和 芝加哥)提供了公共个人信息,证明可行后,我们开始增强服务来处理数据复制、不同源的调用、单向数据复制事件、将用户分配到地理位置更近的数据中心。
我们大多的数据库运行在Espresso(一个新的内部多用户数据仓库)上。
Espresso支持多个数据中心,提供了 主-主 的支持,及支持很难的数据复制。

多个数据中心对于高可用性具有不可思议的重要性,你要避免的单点故障不仅仅是某个服务失效,更要担心整个站点失效。今天,LinkedIn运行了3个主数据中心,同时还有全球化的PoPs服务。
LinkedIn's operational setup as of 2015 (circles represent data centers, diamonds represent PoPs)

我们还做了哪些工作?

当然,我们的扩展故事永远不会这么简单。我们的工程和运维团队这些年做了不计其数的工作,主要包括这些大的创新:
这些年很多最关键系统都有自己丰富的扩展演化历史,包括会员图服务(Leo之外的第一个服务),搜索(第二个服务),新闻种子,通讯平台及会员信息后台。

我们还构建了数据基础平台支持长期的增长,这是Databus和Kafka的第一次实战,后来用Samza做数据流服务,Espresso和Voldemort作存储解决方案,Pinot用来分析系统,以及其它自定义解决方案。另外,我们的工具也得到了提升,这样工程师就可以自动化布署这些基础架构。

我们还使用Hadoop和Voldemort数据开发了大量的离线工作流,用以智能分析,如“你可能认识的人”,“相似经历”,“感觉兴趣的校友”及“个人简历浏览地图”。

我们重新考虑了前端的实现,增加客户端模板到混合页面(个人中心、我的大学页面),这样应用可以更加可交互,只要我们的服务器发送JSON或部分JSON数据。此外,模板页面通过CDN和浏览器缓存。我们也开始使用了BigPipe和Play框架,把我们的模型从线程化的服务器变成非阻塞异步的服务器。

除了代码,我们使用了Apache Traffic Server做多层代理和用HAProxy做负载均衡,数据中心,安全,智能路由,服务端渲染等等。

最后,我们继续提升服务器的性能,包含优化硬件,内存和系统的高级优化,使用更新的JRE。

下一步

LinkedIn今天仍在快速增长,仍有大量值得提升的工作要做,我们正在解决一些问题,看起来只解决了一部分 - 快来加入我们吧!

感谢Steve, Swee, Venkat, Eran, Ram, Brandon, Mammad, 和 Nick的审阅和帮助

转载于:https://www.cnblogs.com/zhengran/p/4675199.html

[转载] LinkedIn架构这十年相关推荐

  1. LinkedIn架构这十年

    原文: A Brief History of Scaling LinkedIn 2003年是LinkedIn元年,公司成立的目标是连接你的个人人脉以获得更好的的工作机会.上线第一周才有2700个会员注 ...

  2. 转载:程序员的十层楼

    转载:程序员的十层楼 By 周伟明@英特尔 程序员的十层楼(1~3层) 自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外.当然现在中国的许多程序员们对此可能有许多不同的意见,有些人 ...

  3. linkedin 架构_投票:您如何使用LinkedIn?

    linkedin 架构 Business social network LinkedIn announced that they've turned on their OpenSocial-power ...

  4. 从零学习 InfiniBand-network架构(十) —— IB协议中全局ID

    从零学习 InfiniBand-network架构(十) -- IB协议中全局ID

  5. linkedin 架构_如何通过linkedin消息发现网络钓鱼

    linkedin 架构 Just a few days after been falsely accused by my former web host of operating a phishing ...

  6. GUI 应用程序架构的十年变迁:MVC、MVP、MVVM、Unidirectional、Clean

    随着现代浏览器的日渐流行,Web 以及混合开发技术的发展,大前端的概念日渐成为某种共识:而无论 iOS.Android.Web 这样的端开发还是 React Native.Weex 这样的跨端开发,其 ...

  7. 淘宝服务端高并发分布式架构的十四次演进之路

    1.概述 本文以淘宝作为例子,介绍从一百个并发到千万级并发情况下服务端的架构的演进过程,同时列举出每个演进阶段会遇到的相关技术,让大家对架构的演进有一个整体的认知,文章最后汇总了一些架构设计的原则. ...

  8. 【转载】架构师速成-如何高效编程

    引子 赵云大喝一声,挺枪骤马杀入重围,左冲右突,如入无人之境.那枪浑身上下,若舞梨花:遍体纷纷,如飘瑞雪. 赵云是所有历史人物中我最喜欢的一个,如果放到现代,他走了it的道路,一定可以成为一个编程高手 ...

  9. 《InsideUE4》GamePlay架构(十)总结

    世界那么大,我想去看看 引言 通过对前九篇的介绍,至此我们已经了解了UE里的游戏世界组织方式和游戏业务逻辑的控制.行百里者半九十,前述的篇章里我们的目光往往专注在于特定一个类或者对象,一方面固然可以让 ...

最新文章

  1. android 应用变量,Android全局应用变量的使用
  2. R语言使用lubridate包的tz函数设置和查询日期、时间对象的时区信息( time zone)
  3. 第四周实践项目7 多项式求和
  4. centos7 ifconfig命令找不到_分享一个解决 sudo 命令找不到环境变量的小技巧
  5. modules runAllManagedModulesForAllRequests=true /(转1)
  6. Angular应用ng serve命令行的学习笔记
  7. python课堂笔记之django-day02(7)
  8. 小米集团2021年Q4净利润45亿元 同比增长39.6%
  9. [面试] C/C++语法(三)—— 字符串
  10. php 采集网站关键字,php远程获取网站的关键字信息(并附:php判断字符串编码)...
  11. IMU噪声参数辨识-艾伦方差
  12. OIBH杯第三次普及组模拟赛T1 立体井字棋
  13. usage.txt-2
  14. 斑马Zebra 110Xi4 打印机驱动
  15. MD5在文件中的使用
  16. vs2017无法解析外部符号__imp__fprintf和__imp____iob_func
  17. node文件系统 常用文件处理方法
  18. 万能和弦与和弦走向浅析
  19. Mysql 条件查询(like、between、and、in······)
  20. java 将字符串首字母变大写

热门文章

  1. Object.prototype.toString.call()检测
  2. Nginx+Tomcat负载均衡
  3. [翻译]RobotTurK: 灾难情况紧急视频系统
  4. https://toonify.photos/ for Disney style
  5. 当linkedin connection达到1500的时候的感受
  6. 【转】直线光栅化算法-Bresenham算法
  7. Python数据类型(列表和元组)
  8. NodeJs 创建一个简单的服务
  9. html head
  10. springmvc 实现javamail