解剖Twitter
[2] 三层架构
[3] Cache == Cash
[4] 抗洪需要隔离
[5] 数据流与控制流
[6] 流量洪峰与云计算
[7] 作为一种进步的不彻底
[8] 得过不且过
[9] 结语
【5】数据流与控制流
前文说到,Twitter有两大看点,缓存(Cache) 与消息队列(Message Queue)。消息队列的作用,是“隔离用户请求与相关操作,以便烫平流量高峰 (Move operations out of the synchronous request cycle, amortize load over time)”。
通过让Apache进程空循环的办法,迅速接纳用户的访问,推迟服务,说白了是个缓兵之计,目的是让用户不至于收到“HTTP 503”错误提示,“503错误”是指“服务不可用(Service Unavailable)”,也就是网站拒绝访问。
大禹治水,重在疏导。真正的抗洪能力,体现在蓄洪和泄洪两个方面。蓄洪容易理解,就是建水库,要么建一个超大的水 库,要么造众多小水库。泄洪包括两个方面,1. 引流,2. 渠道。
对于Twitter系统来说,庞大的服务器集群,尤其是以MemCached为主的众多的缓存,体现了蓄洪的容量。引流的手段是Kestrel消息队列,用于传递控制指令。渠道是机器与机器之间的数据传输通道, 尤其是通往MemCached的数据通道。渠道的优劣,在于是否通畅。
Twitter的设计,与大禹的做法,形相远,实相近。Twitter系统的抗洪措施,体现在有效地控制数据流,保证在洪峰到达时,能够及时把数据疏散到多个机器上去,从而避免压力过度集中,造成整个系统的瘫痪。
2009年6月,Purewire公司通过爬Twitter网站,跟踪Twitter用户之间“追”与“被追”的关系,估算出Twitter用户总量在7,000,000左右 [26]。在这7百万用户中,不包括那些既不追别人,也不被别人追的孤立用户。也不包括孤岛人群,孤岛内的用户只相互追与被追,不与外界联系。如果加上这些孤立用户和孤岛用户群,目前Twitter的用户总数,或许不会超过1千万。
截止2009年3月,中国移动用户数已达4.7亿户[27]。如果中国移动的飞信[28] 和139说客[29] 也想往Twitter方向发展,那么飞信和139的抗洪能力应该设计到多少呢?简单讲,需要把Twitter系统的现有规模,至少放大47倍。所以,有人这样评论移动互联网产业,“在中国能做到的事情,在美国一定能做到。反之,不成立”。
但是无论如何,他山之石可以攻玉。这就是我们研究Twitter的系统架构,尤其是它的抗洪机制的目的。
Figure 7. Twitter internal flows
下面举个简单的例子,剖析一下Twitter网站内部的流程,借此考察Twitter系统有哪些机制,去实现抗洪的三要素,“水库”、“引流”和 “渠道”。
假设有两个作者,通过浏览器,在Twitter网站上发表短信。有一个读者,也通过浏览器,访问网站并阅读他们写的短信。
1. 作者的浏览器与网站建立连接,Apache Web Server分配一个进程(Worker Process)。作者登录,Twitter查找作者的ID,并作为Cookie,记忆在HTTP邮包的头属性里。
2. 浏览器上传作者新写的短信(Tweet),Apache收到短信后,把短信连同作者ID,转发给Mongrel Rails Server。然后Apache进程进入空循环,等待Mongrel的回复,以便更新作者主页,把新写的短信添加上去。
3. Mongrel收到短信后,给短信分配一个ID,然后把短信ID与作者ID,缓存到Vector MemCached服务器上去。
同时,Mongrel让Vector MemCached查找,有哪些读者“追”这位作者。如果Vector MemCached没有缓存这些信息,Vector MemCached自动去MySQL数据库查找,得到结果后,缓存起来,以备日后所需。然后,把读者IDs回复给Mongrel。
接着,Mongrel把短信ID与短信正文,缓存到Row MemCached服务器上去。
4. Mongrel通知Kestrel消息队列服务器,为每个新短信开设一个队列,队列的名称中隐含短信ID。
对应于每个短信,Mongrel已经从Vector MemCached那里知道,有哪些读者追这条短信的作者。Mongrel把这些读者的IDs,逐个放进这个短信的队列。假如短信二的作者是作者二,他有两个读者,Follower7和Follower3,那么第二个短信的队列中将有两个消息,分别包括Follower7和Follower3的IDs。
5. 同一台Mongrel Server,或者另一台Mongrel Server,在处理某个Kestrel队列中的消息前,从这个队列的名称中解析出相应的短信ID。
然后Mongrel从Row MemCached缓存器中,查找对应于这个短信ID的短信正文。
Mongrel从Kestrel队列中,逐个提取消息,解析消息中包含的读者ID。得到读者ID,以及短信正文后,Mongrel更新该读者的主页,添加 上这条短信的正文。同时,也更新作者的主页,也添加这条短信的正文。
6. Mongrel把更新后的作者的主页,传递给正在空循环的Apache的进程。该进程把作者主页主动传送(push)给作者的浏览器。
如果读者的浏览器事先已经登录Twitter网站,建立连接,那么Apache给该读者也分配了一个进程,该进程也处于空循环状态。Mongrel把更新后的读者的主页,传递给相应进程,该进程把读者主页主动传递给读者的浏览器。
咋一看,流程似乎不复杂。“水库”,“引流”和“渠道”,这抗洪三要素体现在哪里呢?盛名之下的Twitter,妙处何在?值得细究的看点很多。
Reference:
[26] Twitter user statistics by Purewire, June 2009.
(http://www.nickburcher.com/2009/06/twitter-user-statistics-purewire-report.html)
[27] 截止2009年3月,中国移动用户数已达4.7亿户.
(http://it.sohu.com/20090326/n263018002.shtml)
[28] 中国移动飞信网. (http://www.fetion.com.cn/)
[29] 中国移动139说客网. (http://www.139.com/)