深度剖析:Twitter怎样支持上亿用户 - 个人文章 - SegmentFault

标签: | 发表时间:2018-01-15 20:09 | 作者:
出处:https://segmentfault.com

谈到设计Twitter, 我们首先要问一个本质问题:设计Twitter的基本方法论是什么?

其实是我们计算机设计最基本的方法:分治法(Divide and Conquer)。

什么是分治法呢?就是把问题不断的拆解,拆解到你可以解决为止,它的艺术在于,从哪个维度来拆解非常考验我们能力。

你的架构是什么样的呢?

相信你一定不会给出复杂的架构。前端是各种各样的业务逻辑,后端是MySQL数据库,这样就够了。因为这已经解决了当时的问题,满足了一周开发出来的要求。

但随着Twitter的成长,我们会遇到各种各样新的挑战:

MySQL难扩展。
为什么难扩展?因为它把同样的一个数据分成各种关系存在里面,每次取的时候,都要通过Join来进行复杂的操作,这个Join当数据被切分的时候存在更多的服务器上,会变得越来越复杂,所以很难扩展。
小变化也要全部部署。
任何变化都需要部署到所有机器上,因为服务不断升级,就变成了每天不断部署,变成了daily deployment。所以每次部署的时候耽误时间很长。
性能差。
因为所有服务都要部署在一起,造成了它的内存占用率大,而且部分核心模块还因为最初当时的单线程设计成为了各种瓶颈。
架构混乱。
因为所有模块在一起很混乱。
那要怎么破解这些问题?

答案是将问题拆解开来。

第一刀将存储切开。

我们看后台,可以拆成存Tweets,存User,存Timeline,存Social Graph不同内容,Timeline可以拿Redis这样的数据库来保存,而对于其它的数据比如Gizzard其实是一个分布式的MySQL数据库。并不是所有数据都不适合用MySQL分布,我们可以把这些适合的用MySQL来shutting一下,而不适合的用别的数据库来存,就是一个存储切开的方法。

第二刀是将路由、展示、逻辑切开。

我们可以看到又多出了一层,逻辑层。Tweets,User,Timeline它们分别对应后边的各种数据存储。前端会有外部访问的接口,API访问接口,并且它还保存了以前数据的整个架构,用来进行一些小规模的使用。最前面需要有一个Routing,来将不同的请求分布到不同的API上。所以之后Twitter就变成了上百上千个小小的数据模块,包括它的服务模块,他们通过之间的相互调用来完成具体的请求。

如果Lady Gaga发了个推文,会发生什么呢?

首先她发出一个推文,会到达最上面一层的外部模块,负责把推文写出来;接着到了API模块,负责接收这个推文;再往后是Fanout,Fanout将推文的ID推荐给所有订阅这个用户的信息收件箱里,收件箱就是Timeline,比如有400万人订阅了Lady Gaga,就会有400万的收件箱收到这个消息;紧接着由于我们Timeline要发到收件箱里,收件箱必然是一个最复杂的操作,为了优化它的性能,就把它们用分布式的方式存储在Redis里面,Redis是偏向内存的数据库,所以能够很快的存储这些信息;但Redis里存的只是ID,所以当一个用户具体要她推文的时候,实际上要通过Timeline服务去找到这个用户对应的是哪个Redis服务器上存了推文的 Timeline list,接着找到所有ID,然后这个Timeline service把ID的具体内容通过另外的数据库装载进来,最终得到结果反馈给用户。这些保证了我们推整个数据的时候速度最快,能够达到每秒30万次的性能。

虽然有了这样的过程,如何支持搜索呢?

很简单的想法是当我们写入API,它Fanout到每个用户的Timeline list的时候,我们可以拿另外的Ingester把这个推文放到里面,Ingesert最后把它放到Earlybird,就是所谓的倒排索引中。比如有个推文发过来“我喜欢太阳”,就把我,喜欢,太阳,拆成三个词,把这些单词,进行倒排索引,存到Search index里面。这时候实际会用到很多很多Earlybird,这样就能建立很多倒排索引,能够并行的去做。当用户一个请求过来之后,比如搜索“早上吃饭”,就会把morning和eat作为两个关键词发到我的Earlybird集群里,得到结果后Blender会把它组合到一块,并反馈结果。当然很多用户可以并行的向Blender发送请求,从而得到最终结果,这就是我们的搜索服务。

如何通知用户新消息到达呢?

第一个方法是另外再开一个Write API,在有新东西发生以后,我把它放到一个Push的服务里,那所有用户只要都连到这个后台里,HTTP PUSH,就会通知他有新消息产生了。同理对Mobile ,会有Mobile Push,当然大家对不同的信息有不同的对接方法,大家可以去仔细考虑下怎么能做到这个样子。

如何搭建这样的服务呢?

最基本的是开源项目Twitter-Server。

配置服务,IP之类;
管理服务,哪些down了、控制、启动等;
日志服务,运行怎么样,以后出问题找谁等;
生命周期服务,什么时候启,什么时候关,什么时候控制;
监控服务,到底有没有出错,出错以后怎么办,互相报警等
这些东西合到一起,就构成了这样服务的基本架构。

各个服务之间如何交流?

这就是传统的RPC(远程的进程调用),大家能够通讯的不仅是数据,而且可以通讯命令或请求之类的。这时需要开源项目Finagle。

能够提供服务发现,因为有很多服务,所以要找谁发送这个请求呢;
负载均衡,可能有十个人提供服务,先放到谁那儿?
重试,如果失败了怎么办,是否需要重试?
基本的线程池和链接池,大家可以复用,不用每次去创建,浪费资源了;
统计信息的收集;
分布式调试。
如何调用一个服务?

因为从A调用B,大家之间各种远程,写代码上要怎么做呢?可以使用函数来调用(Service as a Function),背后实际上是Function programming的思想。

可以看下这个基本例子:trait Service[Req,Rep]extends(Req=>Future[Rep])

简单理解为:我有一个请求想得到一个Response,就是Request到Response。这里面实际上可以先面向未来实现,之后当它执行的时候,就会得到相对应的结果。

多个服务的调用如何整合在一起?

我们看一看它要如何运行?比如我们有一个请求是得到一个用户的所有Timeline数据。它其实有很多步,第一步是得到User ID;第二步得到User timeline list里的那些消息ID;下一步是针对每一个消息,得到它的每一个具体内容,比如“我早上吃饭”这些内容,这些内容里面可能还有图片,还需要得到图片的数据。这是一个很复杂的过程,但这个箭头表达了它们最基本的执行顺序。

最佳的执行路径是什么?

首先是得到ID,再得到Timeline以后可以并行地读取每个tweet,可能会有的快有的慢,然后又得到一些它的具体信息,比如说图片之类,所以这就是最优策略。

下面我们来看一看代码:

第一行是得到用户ID,用一个面向未来的方程得到一个用户ID。

p其实是后面针对每一个ID执行的函数,这个函数来得到这个ID用户的Timeline list。所以这也是我们Function programming,或者如果用Spark也会经常碰见的函数。

得到每一个ID以后,实际上要针对每个ID执行,所以需要Map。Map每一个ID是做什么的,得到这个Tweet的具体信息。代码第二行就是根据ID得到他的具体内容。

当然如果这个东西有图片,那需要得到图片。

中间一步还需要把这些东西并行起来,大家都去单独得到Tweet,并且把它集合放到一块儿去。整个过程我们就得到了最终的代码。

这其实就是第三刀:切开“做什么”和“怎么做”。在这个代码过程中,所谓面向函数的编程,只是写了想做什么事儿,但具体怎么做,比如从哪个机器找、连接服务器、从谁那儿抓取,怎么并行等都没有写,实际上这些东西都被封装到了一个底层的库里面。所以现在Twitter就可以有两个团队,一个团队负责写代码,“做什么”;另一个团队负责写底层是怎么实现的。这样就能实现并行开发,这也是Function programming的一个好处。

一个服务器的架构长什么样呢?

上方是你的服务,下方就是你的服务器,包括一些集群的管理、内存、Java的虚拟机、操作系统和硬件。

有很多服务如何整合?

结果整合到一起就是很多层,底层都是一样的,但上层跑了不同的服务:HTTP、聚集器、时间timeline服务等。我们所有东西加在一起,系统就会跑上千个不同的小服务器,而且之间会有各种各样的备份。

那如何来统计出现的服务器情况呢?

比如会统计平均延迟,或统计一些信息来验证服务器是不是出问题了,实际上,在这种大规模里面,一个比较好的方法就是不要拿平均值统计,因为特殊情况会拉低所有情况。举个例子,假设北京有一个人,他年收入是100万,另外99个人每个人年收入都是1元。那平均下来每个人收入都是1万块钱,但实际上大多数人是很穷困的。所以不能拿平均数来算,尤其是在服务器的情况下。所以大家一般都会取中位数(median),百分之90的点,百分之99的点和百分之999的点。我们可以看到,下图是一个服务发生故障的前后。在服务故障发生前,百分之99点的平均延迟是100毫秒,但故障发生后变成400毫秒,发现这个问题以后就会去抓。但如果用平均值,很可能就发现不了这个问题。

这样还有一个好处,当我们做到上面整合的架构以后,每一个负责写代码的团队,只负责处理跟它相关的上下层就行,而不用做那么多交互,所以每个人的东西都非常简单,这也是所谓微服务的一个好处。

如何监控一个服务呢?

实际上针对这个服务在整个栈里面用的时间,会有一个图表达出来。

如何监控一个请求呢?

实际上,基于一个请求,会有一个整个运行的最佳策略,这就需要运行的整个过程的图。这就是我们之前讲的,得到一个用户所有Timeline内容信息的锯齿图,Zipkin,这也是一个开源项目。

如何监控系统的运行情况呢?

因为这个时候失败已经成为常事了。举个例子,假设每秒有30万的请求,有99.99%的成功率,那每秒一定会有30个失败的,所以不能说每次失败怎么样,统计失败率会比单独的失败更重要,而且写代码的时候要为这个失败来进行自动重试。大家不用纠结每次的失败,只要大部分过去就行了。

最后做下总结

学好分治法,走遍天下都不怕。
函数式设计切分做什么和怎么做。做什么是由函数式设计来写,而怎么做由底层的语言和编译器来优化。
面向错误让我们使用了统计域监控。99.9%的点出什么问题了,这样就叫做基于统计域的监控方式。


相关 [深度 twitter 用户] 推荐:

深度剖析:Twitter怎样支持上亿用户 - 个人文章 - SegmentFault

- -
谈到设计Twitter, 我们首先要问一个本质问题:设计Twitter的基本方法论是什么. 其实是我们计算机设计最基本的方法:分治法(Divide and Conquer). 就是把问题不断的拆解,拆解到你可以解决为止,它的艺术在于,从哪个维度来拆解非常考验我们能力. 前端是各种各样的业务逻辑,后端是MySQL数据库,这样就够了.

Lab42:Twitter 用户习惯调查

- Tony - 爱范儿 · Beats of Bits
Lab42 针对 500 名 Twitter 用户做了使用习惯调查. 譬如他们用 Twitter 的目的、如何决定 Follow 别人等. Lab42 把调查结果用信息图形是表现出来,比较有趣,一起来看下吧. 33% 的人单日多次登录 Twitter,19% 的人一周会登录几次. 至于通过何种方式访问 Twitter,超过半数的人选择直接电脑登陆官网,16% 的选择官方移动版.

一个Twitter用户的忏悔

- 山坡羊 - 36氪
2008年6月25号那天,我发了第一条推:“测试,测试,是这样么. ”我希望它可以让我的朋友们笑笑,以此作为一个好的开始. 我当时完全不知道,我会多么神速的沉浸到Twitter中去. 不久之后,我开始一周七天每天发推,一天20-30条. 其中有些很有趣,有些很悲伤,有些含糊不清 – “永远快乐的方法就是杀了我”- 有些很轻浮,有些很猥琐.

语言学家开发出算法识别Twitter用户性别

- geek2live - Solidot
网民多以假名掩盖身份,雌雄难辩,男扮女女扮男屡见不鲜,然而他们的言语和喜好会暴露他们的身份. Mitre公司的语言学研究人员,在苏格兰举行的自然语言处理实证方法会议上公布了一篇论文(PDF),称他们开发出一种算法能根据Twitter用户的帖子内容识别出其性别,他们的依据是女性所用语言和男性存在相当大的差异.

Twitter面向iPad用户发布HTML5新界面

- psyZETA - cnBeta.COM
用iPad访问Twitter的用户们今天可以看到全新的界面,这是昨晚才上线的一个新体验外观,整体风格和iPad用户的应用使用习惯一致,技术上它完全采用HTML5编写,拥有更高的性能和更好的触控操作体验.

Twitter vs.Facebook:哪个的用户对企业更有价值?

- 章明 - 互联网的那点事
几乎有一半的美国成年人经常使用社交网络,而大小企业也都把twitter和facebook当成企业与用户对话的主阵地,通过这些社会化平台与用户互动,吸引新的用户. 但是,这些平台到底哪个对于品牌来说最有价值呢. 下面一张来自buysellads的信息图也许能说明一些事情:. Twitter和facebook的用户群年龄都集中在23岁—35岁之间,分别占比为34%和33%,.

Twitter用户悼念乔布斯:没有你世界会不同

- David - cnBeta.COM
新浪科技讯 北京时间10月6日上午消息,苹果创始人史蒂夫・乔布斯(Steve Jobs)周三骤然辞世,整个科技行业陷入了悲痛之中,他们也通过Twitter表达着自己的哀思. 大量Twitter用户通过短短140个字悼念这位传奇人物,哀伤程度是任何企业领袖逝世都无法相比的. Twitter为全球数以亿计受益于乔布斯和苹果创新的用户提供了一个表达他们情感的窗口.

Twitter达到1亿「活跃」用户,将支持中文界面

- Ruby - 36氪
Twitter 今天在官方博客宣布,他们的活跃用户达到了 1 亿,其中 55% 使用手机登陆. Twitter.com 每月有 4 亿的独立访客. 在这些活跃用户中,有 40% 的人实际上并不发推,他们只是登陆后看自己关注的人在说什么. 在接下来的几周内,Twitter 将推出简体中文语言和繁体中文语言版本,那时 Twitter 将一共支持 17 种不同语言.

谷奥: Google+ 也将有 Twitter 那种推荐用户列表

- ming - 谷奥聚合——谷奥主站+谷安 aggregator
Google的Bradley Horowitz发推说Google+也将增加类似Twiter的推荐用户功能,就是强推给你一些他们觉得对你有用的用户. 他在征集Twitter被10万人以上follow的名人直接联系他,很显然是想将此人拉到Google+,而交换条件就是将他放上推荐用户列表. 不过我们还不清楚Google到底想如何来推荐用户.

[信息图]twitter用户最爱问什么问题?

- Shiming - cnBeta.COM
人们使用tiwtter的目的千差万别,有的是为了获得最新消息,有的是想和朋友同事保持联络,有的是想问他们的粉丝一些问题,下面这张信息图在新浪微博 上传了有几天了,我看其中有些细节值得关注,翻译成中文和大家分享下.