解剖Twitter文档格式.docx
- 文档编号:21083718
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:25
- 大小:2.75MB
解剖Twitter文档格式.docx
《解剖Twitter文档格式.docx》由会员分享,可在线阅读,更多相关《解剖Twitter文档格式.docx(25页珍藏版)》请在冰豆网上搜索。
前半句正确,但是后半句有商榷余地。
Twitter的竞争力,离不开严谨的系统架构设计。
【1】万事开头易
Twitter的核心业务逻辑,在于Following和Befollowed。
[5]
进入Twitter个人主页,你会看到你following的那些作者,最近发表的微博客。
所谓微博客,就是一则短信,Twitter规定,短信的长度不得超过140个字。
短信不仅可以包含普通文字信息,也可以包含URL,指向某个网页,或者照片及视频等等。
这就是following的过程。
当你写了一则短信并发表以后,你的followers会立刻在他们的个人主页中看到你写的最新短信。
这就是befollowed的过程。
实现这个业务流程似乎很容易。
1.为每一个注册用户订制一个Be-followed的表,主要内容是每一个follower的ID。
同时,也订制一个Following的表,主要内容是每一个following作者的ID。
2.当用户打开自己的个人空间时,Twitter先查阅Following表,找到所有following的作者的ID。
然后去数据库读取每一位作者最近写的短信。
汇总后按时间顺序显示在用户的个人主页上。
3.当用户写了一则短信时,Twitter先查阅Be-followed表,找到所有followers的IDs。
然后逐个更新那些followers的主页。
如果有follower正在阅读他的Twitter个人主页,主页里暗含的JavaScript会自动每隔几十秒,访问一下Twitter服务器,检查正在看的这个个人主页是否有更新。
如果有更新,立刻下载新的主页内容。
这样follower就能读到最新发表的短信了。
从作者发表到读者获取,中间的延迟,取决于JavaScript更新的间隔,以及Twitter服务器更新每个follower的主页的时间。
从系统架构上来说,似乎传统的三段论(Three-tierarchitecture[6]),足够满足这个业务逻辑的需要。
事实上,最初的Twitter系统架构,的确就是三段论。
Reference,
[1]FixingTwitter.(
[2]TwitterblowsupatSXSWconference.(
[3]FirstHandAccountsofTerroristAttacksinIndiaonTwitterandFlickr.(
[4]SocialMediaTakesCenterStageinIran.(
[5]Twitter的这些那些.((
[6]Threetierarchitecture.http:
//en.wikipedia.org/wiki/Multitier_architecture
【2】三段论
网站的架构设计,传统的做法是三段论。
所谓“传统的”,并不等同于“过时的”。
大型网站的架构设计,强调实用。
新潮的设计,固然吸引人,但是技术可能不成熟,风险高。
所以,很多大型网站,走的是稳妥的传统的路子。
2006年5月Twitter刚上线的时候,为了简化网站的开发,他们使用了Ruby-On-Rails工具,而Ruby-On-Rails的设计思想,就是三段论。
1.前段,即表述层(PresentationTier)用的工具是ApacheWebServer,主要任务是解析HTTP协议,把来自不同用户的,不同类型的请求,分发给逻辑层。
2.中段,即逻辑层(LogicTier)用的工具是MongrelRailsServer,利用Rails现成的模块,降低开发的工作量。
3.后段,即数据层(DataTier)用的工具是MySQL数据库。
先说后段,数据层。
Twitter的服务,可以概括为两个核心,1.用户,2.短信。
用户与用户之间的关系,是追与被追的关系,也就是Following和Befollowed。
对于一个用户来说,他只读自己“追”的那些人写的短信。
而他自己写的短信,只有那些“追”自己的人才会读。
抓住这两个核心,就不难理解Twitter的其它功能是如何实现的[7]。
围绕这两个核心,就可以着手设计DataSchema,也就是存放在数据层(DataTier)中的数据的组织方式。
不妨设置三个表[8],
1.用户表:
用户ID,姓名,登录名和密码,状态(在线与否)。
2.短信表:
短信ID,作者ID,正文(定长,140字),时间戳。
3.用户关系表,记录追与被追的关系:
用户ID,他追的用户IDs(Following),追他的用户IDs(Befollowed)。
再说中段,逻辑层。
当用户发表一条短信的时候,执行以下五个步骤,
1.把该短信记录到“短信表”中去。
2.从“用户关系表”中取出追他的用户的IDs。
3.有些追他的用户目前在线,另一些可能离线。
在线与否的状态,可以在“用户表”中查到。
过滤掉那些离线的用户的IDs。
4.把那些追他的并且目前在线的用户的IDs,逐个推进一个队列(Queue)中去。
5.从这个队列中,逐个取出那些追他的并且目前在线的用户的IDs,并且更新这些人的主页,也就是添加最新发表的这条短信。
以上这五个步骤,都由逻辑层(LogicTier)负责。
前三步容易解决,都是简单的数据库操作。
最后两步,需要用到一个辅助工具,队列。
队列的意义在于,分离了任务的产生与任务的执行。
队列的实现方式有多种,例如ApacheMina[9]就可以用来做队列。
但是Twitter团队自己动手实现了一个队列,Kestrel[10,11]。
Mina与Kestrel,各自有什么优缺点,似乎还没人做过详细比较。
不管是Kestrel还是Mina,看起来都很复杂。
或许有人问,为什么不用简单的数据结构来实现队列,例如动态链表,甚至静态数组?
如果逻辑层只在一台服务器上运行,那么对动态链表和静态数组这样的简单的数据结构,稍加改造,的确可以当作队列使用。
Kestrel和Mina这些“重量级”的队列,意义在于支持联络多台机器的,分布式的队列。
在本系列以后的篇幅中,将会重点介绍。
最后说说前段,表述层。
表述层的主要职能有两个,1.HTTP协议处理器(HTTPProcessor),包括拆解接收到的用户请求,以及封装需要发出的结果。
2.分发器(Dispatcher),把接收到的用户请求,分发给逻辑层的机器处理。
如果逻辑层只有一台机器,那么分发器无意义。
但是如果逻辑层由多台机器组成,什么样的请求,发给逻辑层里面哪一台机器,就大有讲究了。
逻辑层里众多机器,可能各自专门负责特定的功能,而在同功能的机器之间,要分摊工作,使负载均衡。
访问Twitter网站的,不仅仅是浏览器,而且还有手机,还有像QQ那样的电脑桌面工具,另外还有各式各样的网站插件,以便把其它网站联系到T上来[12]。
因此,Twitter的访问者与Twitter网站之间的通讯协议,不一定是HTTP,也存在其它协议。
三段论的Twitter架构,主要是针对HTTP协议的终端。
但是对于其它协议的终端,Twitter的架构没有明显地划分成三段,而是把表述层和逻辑层合二为一,在Twitter的文献中,这二合一经常被称为“API”。
综上所述,一个能够完成Twitter基本功能的,简单的架构如Figure1所示。
或许大家会觉得疑惑,这么出名的网站,架构就这么简单?
YesandNo,2006年5月Twitter刚上线的时候,Twitter架构与Figure1差距不大,不一样的地方在于加了一些简单的缓存(Cache)。
即便到了现在,Twitter的架构依然可以清晰地看到Figure1的轮廓。
Figure1.Theessential3-tierofTwitterarchitecture
Courtesy
Reference,
[7]Tweets中常用的工具(
[8]构建基于PHP的微博客服务(
[9]ApacheMinaHomepage(http:
//mina.apache.org/)
[10]KestrelReadme(
[11]AWorkingGuidetoKestrel.(
[12]AlphabeticalListofTwitterServicesandApplications(http:
//en.wikipedia.org/wiki/List_of_Twitter_services_and_applications)
【3】Cache==Cash
Cache==Cash,缓存等于现金收入。
虽然这话有点夸张,但是正确使用缓存,对于大型网站的建设,是至关重要的大事。
网站在回应用户请求时的反应速度,是影响用户体验的一大因素。
而影响速度的原因有很多,其中一个重要的原因在于硬盘的读写(DiskIO)。
Table1比较了内存(RAM),硬盘(Disk),以及新型的闪存(Flash),在读写方面的速度比较。
硬盘的读写,速度比内存的慢了百万倍。
所以,要提高网站的速度,一个重要措施是尽可能把数据缓存在内存里。
当然,在硬盘里也必须保留一个拷贝,以此防范万一由于断电,内存里的数据丢失的情况发生。
Table1.StoragemediacomparisonofDisk,FlashandRAM[13]
Twitter工程师认为,一个用户体验良好的网站,当一个用户请求到达以后,应该在平均500ms以内完成回应。
而Twitter的理想,是达到200ms-300ms的反应速度[17]。
因此在网站架构上,Twitter大规模地,多层次多方式地使用缓存。
Twitter在缓存使用方面的实践,以及从这些实践中总结出来的经验教训,是Twitter网站架构的一大看点。
Figure2.TwitterarchitecturewithCache
哪里需要缓存?
越是DiskIO频繁的地方,越需要缓存。
前面说到,Twitter业务的核心有两个,用户和短信(Tweet)。
围绕这两个核心,数据库中存放着若干表,其中最重要的有三个,如下所示。
这三个表的设置,是旁观者的猜测,不一定与Twitter的设置完全一致。
但是万变不离其宗,相信即便有所不同,也不会本质区别。
有没有必要把这几个核心的数据库表统统存放到缓存中去?
Twitter的做法是把这些表拆解,把其中读写最频繁的列放进缓存。
1.VectorCacheandRowCache
具体来说,Twitter工程师认为最重要的列是IDs。
即新发表的短信的IDs,以及被频繁阅读的热门短信的IDs,相关作者的IDs,以及订阅这些作者的读者的IDs。
把这些IDs存放进缓存(Storesarraysoftweetpkeys[14])。
在Twitter文献中,把存放这些IDs的缓存空间,称为VectorCache[14]。
Twitter工程师认为,读取最频繁的内容是这些IDs,而短信的正文在其次。
所以他们决定,在优先保证VectorCache所需资源的前提下,其次重要的工作才是设立RowCache,用于存放短信正文。
命中率(HitRateorHitRatio)是测量缓存效果的最重要指标。
如果一个或者多个用户读取100条内容,其中99条内容存放在缓存中,那么缓存的命中率就是99%。
命中率越高,说明缓存的贡献越大。
设立VectorCache和RowCache后,观测实际运行的结果,发现VectorCache的命中率是99%,而RowCache的命中率是95%,证实了Twitter工程师早先押注的,先IDs后正文的判断。
VectorCache和RowCache,使用的工具都是开源的MemCached[15]。
2.FragmentCacheandPageCache
前文说到,访问Twitter网站的,不仅仅是浏览器,而且还有手机,还有像QQ那样的电脑桌面工具,另外还有各式各样的网站插件,以便把其它网站联系到T上来[12]。
接待这两类用户的,是以ApacheWebServer为门户的Web通道,以及被称为“API”的通道。
其中API通道受理的流量占总流量的80%-90%[16]。
所以,继VectorCache和RowCache以后,Twitter工程师们把进一步建筑缓存的工作,重点放在如何提高API通道的反应速度上。
读者页面的主体,显示的是一条又一条短信。
不妨把整个页面分割成若干局部,每个局部对应一条短信。
所谓Fragment,就是指页面的局部。
除短信外,其它内容例如Twitterlogo等等,也是Fragment。
如果一个作者拥有众多读者,那么缓存这个作者写的短信的布局页面(Fragment),就可以提高网站整体的读取效率。
这就是FragmentCache的使命。
对于一些人气很旺的作者,读者们不仅会读他写的短信,而且会访问他的主页,所以,也有必要缓存这些人气作者的个人主页。
这就是PageCache的使命。
FragmentCache和PageCache,使用的工具也是MemCached。
观测实际运行的结果,FragmentCache的命中率高达95%,而PageCache的命中率只有40%。
虽然PageCache的命中率低,但是它的内容是整个个人主页,所以占用的空间却不小。
为了防止PageCache争夺FragmentCache的空间,在物理部署时,Twitter工程师们把PageCache分离到不同的机器上去。
3.HTTPAccelerator
解决了API通道的缓存问题,接下去Twitter工程师们着手处理Web通道的缓存问题。
经过分析,他们认为Web通道的压力,主要来自于搜索。
尤其是面临突发事件时,读者们会搜索相关短信,而不理会这些短信的作者,是不是自己“追”的那些作者。
要降低搜索的压力,不妨把搜索关键词,及其对应的搜索结果,缓存起来。
Twitter工程师们使用的缓存工具,是开源项目Varnish[18]。
比较有趣的事情是,通常把Varnish部署在WebServer之外,面向Internet的位置。
这样,当用户访问网站时,实际上先访问Varnish,读取所需内容。
只有在Varnish没有缓存相应内容时,用户请求才被转发到WebServer上去。
而Twitter的部署,却是把Varnish放在ApacheWebServer内侧[19]。
原因是Twitter的工程师们觉得Varnish的操作比较复杂,为了降低Varnish崩溃造成整个网站瘫痪的可能性,他们便采取了这种古怪而且保守的部署方式。
ApacheWebServer的主要任务,是解析HTTP,以及分发任务。
不同的MongrelRailsServer负责不同的任务,但是绝大多数MongrelRailsServer,都要与VectorCache和RowCache联系,读取数据。
RailsServer如何与MemCached联系呢?
Twitter工程师们自行开发了一个Rails插件(Gem),称为CacheMoney。
虽然Twitter没有公开Varnish的命中率是多少,但是[17]声称,使用了Varnish以后,导致整个T网站的负载下降了50%,参见Figure3.
Figure3.CachedecreasesTloadby50%[17]
[12]AlphabeticalListofTwitterServicesandApplications.
(http:
[13]HowflashchangestheDBMSworld.
(
[14]ImprovingrunningcomponentofTwitter.
EvanWeaver_ImprovingRunningComponentsAtTwitter.pdf)
[15]Ahigh-performance,general-purposed,distributedmemoryobjectcachingsystem.
[16]UpdatingTwitterwithoutservicedisruptions.
[17]FixingTwitter.(
Fixing_Twitter_Improving_the_Performance_and_Scalability_of_the_World_s_
Most_Popular_Micro-blogging_Site_Presentation%20Presentation.pdf)
[18]Varnish,ahigh-performanceHTTPaccelerator.
//varnish.projects.linpro.no/)
[19]HowtouseVarnishinT?
//projects.linpro.no/pipermail/varnish-dev/2009-February/000968.html)
[20]CacheMoneyGem,anopen-sourcewrite-throughcachinglibrary.
【4】抗洪需要隔离
如果说如何巧用Cache是Twitter的一大看点,那么另一大看点是它的消息队列(MessageQueue)。
为什么要使用消息队列?
[14]的解释是“隔离用户请求与相关操作,以便烫平流量高峰(Moveoperationsoutofthesynchronousrequestcycle,amortizeloadovertime)”。
为了理解这段话的意思,不妨来看一个实例。
2009年1月20日星期二,美国总统BarackObama就职并发表演说。
作为美国历史上第一位黑人总统,Obama的就职典礼引起强烈反响,导致Twitter流量猛增,如Figure4所示。
Figure4.TwitterburstduringtheinaugurationofBarackObama,1/20/2009,Tuesday
其中洪峰时刻,Twitter网站每秒钟收到350条新短信,这个流量洪峰维持了大约5分钟。
根据统计,平均每
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 解剖 Twitter
