解决Twitter的“问题”就像玩玩具一样,这是一个很有趣的扩展性比喻。每个人都觉得Twitter很简单,一个菜鸟架构师随便摆弄一下个可伸缩的Twitter就有了,就这么简单。然而事实不是这样,Twitter的工程副总裁RaffiKrikorian细致深入的描述了在Twitter在可伸缩性上的演化过程,如果你想知道Twitter的如何工作—从这里开始吧。Twitter发展太快,一切转瞬即过,但Twitter已经长大了。它从一开始一个在RubyonRails上苦苦挣扎的小网站变成一个以服务为核心驱动的漂亮站点,服务停掉都难得一见,很大的一个转变。Twitter现在有1.5亿全球活跃用户,300KQPS,22MB/秒的流量,系统每天处理4亿条推特数据,用5分钟时间将LadyGaga手尖流淌出的信息传递到她3100万个关注者。一些需要列出来的要点:Twitter不再希望成为一个Web应用程序,Twitter想要成为一套驱动全世界手机客户端的API,作为地球上最大的实时交互工具。Twitter主要在分发消息,而不是生产消息,300KQPS是在读而每秒仅有6000请求在写。不对称,有数量庞大的粉丝,现在正成为一种常见情况。单个用户发送的消息有很多追随者要看到,这是一个大的扇型输出,分发可能很缓慢,Twitter试图保证在5秒以内,但并不能总是达到这个目标,尤其是当名人或名人之间发推特时,这种情况越来越常见,一个可能后果是在还未看到原始消息之前接受到了回复。Twitter做工作是在迎接高关注度用户所写推特读取的挑战。你主页的数据储存在由800多个Redis节点组成的集群上。从你关注的人及你点击的链接Twitter更了解你。可以通过隐私设置的双向以下时不存在。用户关心推特内容本身,但对Twitter而言推特的内容与其基础设施建设几乎无关。需要一个非常复杂的监控和调试系统来跟踪复杂协议栈内的性能问题。传统的遗留问题一直困扰着系统。Twitter是如何工作的?通过Raffi精彩的演讲来发现吧…面临的挑战可靠的实现150万在线用户及300KQPS(主页和搜索访问),响应慢怎么办?可靠的实现是一个对所有推特的select语句,响应忙死卡死。数据扇形输出的解决方案。当接收到新推特时需要弄清楚应该把它发到哪,这样可以更快速简单的读取,不要在读操作上做任何逻辑计算,性能上写要比读慢得多,能做到4000QPS。内部组成平台服务部门负责Twitter的核心基础设施的可扩展性。他们运行的东西为时间轴、微博、用户及社交网络提供服务,包括所有支撑Twitter平台的系统设备。统一内外部客户使用相同的API。为数百万的第三方应用注册支持。支持产品团队,让他们专注产品无系统支撑方面顾虑。致力于容量规划、构建可扩展的后端系统等工作,通过不断更换设施使网站达到意想不到的效果。Twitter有一个架构师部门,负责Twitter整体架构,研究技术改进路线(他们想一直走在前面)。Push、Pull模式每时每刻都有用户在Twitter上发表内容,Twitter工作是规划如何组织内容并把它发送用户的粉丝。实时是真正的挑战,5秒内将消息呈现给粉丝是现阶段的目标。投递意味着内容、投入互联网,然后尽可能快的发送接收。投递将历时数据放入存储栈,推送通知,触发电子邮件,iOS、黑莓及Android手机都能被通知到,还有短信。Twitter是世界上活跃中最大的信息发送机。推荐是内容产生并快速传播的巨大动力。两种主要的时间轴:用户的及主页的。用户的时间轴特定用户发送的内容。主页时间表是一段时间内所有你关注用户发布的内容。线上规则是这样的:@别人是若被@的人你未关注的话将被隔离出来,回复一个转发可以被过滤掉。这样在Twitter对系统是个挑战。Pull模式有针对性的时间轴。像twitter.com主页和home_timeline的API。你请求它才会得到数据。拉请求的不少:通过RESTAPI请求从Twitter获取数据。查询时间轴,搜索的API。查询并尽可能快的返回所有匹配的推特。Push模式Twitter运行着一个最大的实时事件系统,出口带宽22MB/秒。o和Twitter建立一个连接,它将把150毫秒内的所有消息推送给你。o几乎任何时候,Push服务簇上大约有一百万个连接。o像搜索一样往出口发送,所有公共消息都通过这种方式发送。o不,你搞不定。(实际上处理不了那么多)用户流连接。TweetDeck和Twitter的Mac版都经过这里。登录的时,Twitter会查看你的社交图,只会推送那些你关注的人的消息,重建主页时间轴,而不是在持久的连接过程中使用同一个时间轴。查询API,Twitter收到持续查询时,如果有新的推特发布并且符合查询条件,系统才会将这条推特发给相应的连接。高观点下的基于Pull(拉取方式)的时间轴:短消息(Tweet)通过一个写API传递进来。通过负载平衡以及一个TFE(短消息前段),以及一些其它的没有被提到的设施。这是一条非常直接的路径。完全预先计算主页的时间轴。所有的业务逻辑在短消息进入的时候就已经被执行了。紧接着扇出(向外发送短消息)过程开始处理。进来的短消息被放置到大量的Redis集群上面。每个短息下在三个不同的机器上被复制3份。在Twitter每天有大量的机器故障发生。扇出查询基于Flock的社交图服务。Flock维护着关注和被关注列表。Flock返回一个社交图给接受者,接着开始遍历所有存储在Redis集群中的时间轴。Redis集群拥有若干T的内存。同时连接4K的目的地。在Redis中使用原生的链表结构。假设你发出一条短消息,并且你有20K个粉丝。扇出后台进程要做的就是在Redis集群中找出这20K用户的位置。接着它开始将短消息的ID注入到所有这些列表中。因此对于每次写一个短消息,都有跨整个Redis集群的20K次的写入操作。存储的是短消息的ID,最初短消息的用户ID,以及4个字节,标识这条短消息是重发还是回复还是其它什么东东。你的主页的时间轴驻扎在Redis集群中,有800条记录长。如果你向后翻很多页,你将会达到上限。内存是限制资源决定你当前的短消息集合可以多长。每个活跃用户都存储在内存中,用于降低延迟。活跃用户是在最近30天内登陆的twitter用户,这个标准会根据twitter的缓存的使用情况而改变。只有你主页的时间轴会存储到磁盘上。如果你在Redis集群上失败了,你将会进入一个叫做重新构建的流程。查新社交图服务。找出你关注的人。对每一个人查询磁盘,将它们放入Redis中。MySQL通过Gizzard处理磁盘存储,Gizzard将SQL事务抽象出来,提供了全局复制。通过复制3次,当一台机器遇到问题,不需要在每个数据中心重新构建那台机器上的时间轴。如果一条短消息是另外一条的转发,那么一个指向原始短消息的指针将会存储下来。当你查询你主页的时间轴时候,时间轴服务将会被查询。时间轴服务只会找到一台你的时间轴所在的机器。高效的运行3个不同的哈希环,因为你的时间轴存储在3个地方。它们找到最快的第一个,并且以最快速度返回。需要做的妥协就是,扇出将会花费更多的时间,但是读取流程很快。大概从冷缓存到浏览器有2秒种时间。对于一个API调用,大概400ms。因为时间轴只包含短消息ID,它们必须”合成”这些短消息,找到这些短消息的文本。因为一组ID可以做一个多重获取,可以并行地从T-bird中获取短消息。Gizmoduck是用户服务,Tweetypie是短消息对象服务。每个服务都有自己的缓存。用户缓存是一个memcache集群拥有所有用户的基础信息。Tweetypie将大概最近一个半月的短消息存储在memcache集群中。这些暴露给内部的用户。在边界将会有一些读时过滤。例如,在法国过滤掉纳粹内容,因此在发送之前,有读时内容剥离工作。高级搜索与Pull相反,所有计算都在读时执行,这样可以使写更简单。产生一条推特时,Ingester会对其做语法分析找出新建索引的一切东西,然后将其传入一台EarlyBird机器。EarlyBird是Lucene的修改版本,索引储存在内存中。在推特的分发过程中可能被储存在多个由粉丝数量决定的主页时间轴中,一条推特只会存入一个EarlyBird机器中(不包括备份)。Blender进行时间轴的跨数据中心集散查询。为发现与查询条件匹配的内容它查询每个EarlyBird。如果你搜索“纽约时报”,所有分片将被查询,结果返回后还会做分类、合并及重排序等。排序是基于社会化度量的,这些度量基于转发、收藏及评论的数量等。互动信息是在写上完成的,这里会建立一个互动时间轴。当收藏或回复一条推特时会触发对互动时间轴的修改,类似于主页时间轴,它是一系列的活跃的ID,有最受喜欢的ID,新回复ID等。所有这些都被送到Blender,在读路径上进行重计算、合并及分类,返回的结果就是搜索时间轴上看到的东西。Discovery是基于你相关信息的定制搜索,Twitter通过你关注的人、打开的链接了解你的信息,这些信息被应用在Discovery搜索上,重新排序也基于这些信息。Search和Pull是相反的Search和Pull明显的看起来很相似,但是他们在某些属性上却是相反的。在hometimeline时:写操作。tweet写操作引发O(n)个进程写入Redis集群,n代表你的粉丝,如果是这样,处理LadyGaga或是Obama百万粉丝的数据就得用10s的时间,那是很难接受的。所有的Redis集群都支持硬盘处理数据,但是一般都是在RAM里操作的。读操作。通过API或是网络可用O(1)的时间来找到Redis机器。Twitter在寻找主页路径方面做了大量的优化。读操作可在10毫秒完成。所有说Twitter主导消费机制而不是生产机制。每秒可处理30万个请求和6000RPS写操作。在搜索timeline时:写操作。一个tweet请求由Ingester收到并有一个EarlyBird机器来处理。写操作时O(1).一个tweet需要5秒的处理时间,其包括排队等待和寻找路径。读操作。读操作引发O(n)个集群读操作。大多数人不用search,这样他们可以在存储tweets上面更加有效,但是他们得花时间。读需要100毫秒,search不涉及硬盘操作。全部Lucene索引表都放入RAM,这样比放在硬盘更加有效。tweet的内容和基础设施几乎没什么关系。T-birdstores负责tweet所有的东西。大多数tweet内容是放在RAM处理的。如有没再内存中,就用selectquery将内容抓到内存中。只有在search,Trends,或是What’sHappeningpipelines中涉及到内容,honetimeline对此毫不关心。展望:如何使通道更快更有效?Fanout可以慢下来。可以调整到5秒以下,但是有时候不能工作。非常难,特别是当有名人tweet时候,这种情况越来越多。Twitter关注也是非常不对称的。Tweet只提供给定时间内被关注的信息。Twitter更注重你的信息,因为你关注了兰斯.阿姆斯特朗,但是他并没有关注你。由于不存在互相的关注关系,所以社会联系更多是暗示性隐含性。问题是巨大的基数。@ladygaga有3100万关注者。@katyperry有2800万。@barackobama有2300万关注着。当这些人中有人发微博的时候,数据中心需要写大量微薄到各个关注者。当他们开始聊天时候,这是非常大的挑战,而这时刻都在发生着。这些高关注度的Fanout用户是Twitter最大的挑战。在名人原始微薄发出到关注用户之前,回复一直可以看到。这导致整个网站紊乱。LadyGaga的一条微薄到关注用户需要几分钟的时间,所以关注者看到这条微薄时间是在不同时间点上。有些人可能需要大概5分钟的时间才能看到这条微薄,这远远落后于其他人。可能早期收到