# 解剖Twitter 【2】三段论

- 作者：邓侃
- 发布时间：2010-03-08 15:14
- 原文：https://www.ifanr.com/18817

网站的架构设计，传统的做法是三段论。所谓“传统的”，并不等同于“过时的”。大型网站的架构设计，强调实用。新潮的设计，固然吸引人，但是技术可能不成熟，风险高。所以，很多大型网站，走的是稳妥的传统的路子。

2006年5月Twitter刚上线的时候，为了简化网站的开发，他们使用了Ruby-On-Rails工具，而Ruby-On-Rails的设计思想，就是三段论。

1\. 前段，即表述层(Presentation Tier) 用的工具是Apache Web Server，主要任务是解析HTTP协议，把来自不同用户的，不同类型的请求，分发给逻辑层。

2\. 中段，即逻辑层 (Logic Tier）用的工具是Mongrel Rails Server，利用Rails现成的模块，降低开发的工作量。

3\. 后段，即数据层 (Data Tier) 用的工具是MySQL 数据库。

先说后段，数据层。

Twitter 的服务，可以概括为两个核心，1. 用户，2. 短信。用户与用户之间的关系，是追与被追的关系，也就是Following和Be followed。对于一个用户来说，他只读自己“追”的那些人写的短信。而他自己写的短信，只有那些“追”自己的人才会读。抓住这两个核心，就不难理解 Twitter的其它功能是如何实现的\[7\]。

围绕这两个核心，就可以着手设计Data Schema，也就是存放在数据层(Data Tier)中的数据的组织方式。不妨设置三个表\[8\]，

1\. 用户表：用户ID，姓名，登录名和密码，状态（在线与否）。

2\. 短信表：短信ID，作者ID，正文（定长，140字），时间戳。

3\. 用户关系表，记录追与被追的关系：用户ID，他追的用户IDs (Following)，追他的用户IDs (Be followed)。

再说中段，逻辑层。

当用户发表一条短信的时候，执行以下五个步骤，

1\. 把该短信记录到“短信表” 中去。

2\. 从“用户关系表”中取出追他的用户的IDs。

3\. 有些追他的用户目前在线，另一些可能离线。在线与否的状态，可以在“用户表”中查到。过滤掉那些离线的用户的IDs。

4\. 把那些追他的并且目前在线的用户的IDs，逐个推进一个队列(Queue)中去。

5\. 从这个队列中，逐个取出那些追他的并且目前在线的用户的IDs，并且更新这些人的主页，也就是添加最新发表的这条短信。

以上这五个步骤，都由逻辑层(Logic Tier)负责。前三步容易解决，都是简单的数据库操作。最后两步，需要用到一个辅助工具，队列。队列的意义在于，分离了任务的产生与任务的执行。

队列的实现方式有多种，例如Apache Mina\[9\]就可以用来做队列。但是Twitter团队自己动手实现了一个队列，Kestrel \[10,11\]。Mina与Kestrel，各自有什么优缺点，似乎还没人做过详细比较。

不管是Kestrel还是Mina，看起来都很复杂。或许有人问，为什么不用简单的数据结构来实现队列，例如动态链表，甚至静态数组？如果逻辑层只在一台服务器上运行，那么对动态链表和静态数组这样的简单的数据结构，稍加改造，的确可以当作队列使用。Kestrel和Mina这些“重量级”的队列，意义在于支持联络多台机器的，分布式的队列。在本系列以后的篇幅中，将会重点介绍。

最后说说前段，表述层。

表述层的主要职能有两 个，1. HTTP协议处理器(HTTP Processor)，包括拆解接收到的用户请求，以及封装需要发出的结果。2. 分发器(Dispatcher)，把接收到的用户请求，分发给逻辑层的机器处理。如果逻辑层只有一台机器，那么分发器无意义。但是如果逻辑层由多台机器组成，什么样的请求，发给逻辑层里面哪一台机器，就大有讲究了。逻辑层里众多机器，可能各自专门负责特定的功能，而在同功能的机器之间，要分摊工作，使负载均衡。

访问Twitter网站的，不仅仅是浏览器，而且还有手机，还有像QQ那样的电脑桌面工具，另外还有各式各样的网站插件，以便把其它网站联系到 Twitter.com上来\[12\]。因此，Twitter的访问者与Twitter网站之间的通讯协议，不一定是HTTP，也存在其它协议。

三段论的Twitter架构，主要是针对HTTP协议的终端。但是对于其它协议的终端，Twitter的架构没有明显地划分成三段，而是把表述层和逻辑层合二为一，在Twitter的文献中，这二合一经常被称为“API”。

综上所述，一个能够完成Twitter基本功能的，简单的架构如Figure 1 所示。或许大家会觉得疑惑，这么出名的网站，架构就这么简单？Yes and No，2006年5月Twitter刚上线的时候，Twitter架构与Figure 1差距不大，不一样的地方在于加了一些简单的缓存(Cache)。即便到了现在，Twitter的架构依然可以清晰地看到Figure 1 的轮廓。

![解剖Twitter 【2】三段论](http://docs.google.com/File?id=drfcsw8_431dwkx49gk_b)

Figure 1. The essential 3-tier of Twitter architecture   
Courtesy http://farm3.static.flickr.com/2683/4051785892\_e677ae9d33\_o.png

Reference,

\[7\] Tweets中常用的工具 （http://www.ccthere.com/article/2383833）   
\[8\] 构建基于PHP的微博客服务 (http://webservices.ctocio.com.cn/188/9092188.shtml)   
\[9\] Apache Mina Homepage (http://mina.apache.org/)   
\[10\] Kestrel Readme (http://github.com/robey/kestrel)   
\[11\] A Working Guide to Kestrel. (http://github.com/robey/kestrel/blob/master/docs/guide.md)   
\[12\] Alphabetical List of Twitter Services and Applications (http://en.wikipedia.org/wiki/List\_of\_Twitter\_services\_and\_applications)
