解剖 Twitter【3】Cache == Cash

2010-03-08 15:18

Cache == Cash,缓存等于现金收入。虽然这话有点夸张,但是正确使用缓存,对于大型网站的建设,是至关重要的大事。网站在回应用户请求时的反应速度,是影响用户体验的一大因素。而影响速度的原因有很多,其中一个重要的原因在于硬盘的读写 (Disk IO)。

Table 1 比较了内存 (RAM),硬盘 (Disk),以及新型的闪存 (Flash),在读写方面的速度比较。硬盘的读写,速度比内存的慢了百万倍。所以,要提高网站的速度,一个重要措施是尽可能把数据缓存在内存里。当然,在硬盘里也必须保留一个拷贝,以此防范万一由于断电,内存里的数据丢失的情况发生。

解剖Twitter 【3】Cache == Cash

Table 1. Storage media comparison of Disk, Flash and RAM [13]
Courtesy http://farm3.static.flickr.com/2736/4060534279_f575212c12_o.png

Twitter 工程师认为,一个用户体验良好的网站,当一个用户请求到达以后,应该在平均 500ms 以内完成回应。而 Twitter 的理想,是达到 200ms- 300ms 的反应速度 [17]。因此在网站架构上,Twitter 大规模地,多层次多方式地使用缓存。Twitter 在缓存使用方面的实践,以及从这些实践中总结出来的经验教训,是 Twitter 网站架构的一大看点。

解剖Twitter 【3】Cache == Cash

Figure 2. Twitter architecture with Cache
Courtesy http://farm3.static.flickr.com/2783/4065827637_bb2ccc8e3f_o.png

哪里需要缓存?越是 Disk IO 频繁的地方,越需要缓存。

前面说到,Twitter 业务的核心有两个,用户和短信 (Tweet)。围绕这两个核心,数据库中存放着若干表,其中最重要的有三个,如下所示。这三个表的设置,是旁观者的猜测,不一定与 Twitter 的设置完全一致。但是万变不离其宗,相信即便有所不同,也不会本质区别。

1. 用户表:用户 ID,姓名,登录名和密码,状态(在线与否)。
2. 短信表:短信 ID,作者 ID,正文(定长,140 字),时间戳。
3. 用户关系表,记录追与被追的关系:用户 ID,他追的用户 IDs (Following),追他的用户 IDs (Be followed)。

有没有必要把这几个核心的数据库表统统存放到缓存中去?Twitter 的做法是把这些表拆解,把其中读写最频繁的列放进缓存。

1. Vector Cache and Row Cache

具体来说,Twitter 工程师认为最重要的列是 IDs。即新发表的短信的 IDs,以及被频繁阅读的热门短信的 IDs,相关作者的 IDs,以及订阅这些作者的读者的 IDs。把这些 IDs 存放进缓存 (Stores arrays of tweet pkeys [14])。在 Twitter 文献中,把存放这些 IDs 的缓存空间,称为 Vector Cache [14]。

Twitter 工程师认为,读取最频繁的内容是这些 IDs,而短信的正文在其次。所以他们决定,在优先保证 Vector Cache 所需资源的前提下,其次重要的工作才是设立 Row Cache,用于存放短信正文。

命中率 (Hit Rate or Hit Ratio) 是测量缓存效果的最重要指标。如果一个或者多个用户读取 100 条内容,其中 99 条内容存放在缓存中,那么缓存的命中率就是 99%。命中率越高,说明缓存的贡献越大。

设立 Vector Cache 和 Row Cache 后,观测实际运行的结果,发现 Vector Cache 的命中率是 99%,而 Row Cache 的命中率是 95%,证实了 Twitter 工程师早先押注的,先 IDs 后正文的判断。

Vector Cache 和 Row Cache,使用的工具都是开源的 MemCached [15]。

2. Fragment Cache and Page Cache

前文说到,访问 Twitter 网站的,不仅仅是浏览器,而且还有手机,还有像 QQ 那样的电脑桌面工具,另外还有各式各样的网站插件,以便把其它网站联系到 Twitter.com 上来 [12]。接待这两类用户的,是以 Apache Web Server 为门户的 Web 通道,以及被称为 “API” 的通道。其中 API 通道受理的流量占总流量的 80%-90% [16]。

所以,继 Vector Cache 和 Row Cache 以后,Twitter 工程师们把进一步建筑缓存的工作,重点放在如何提高 API 通道的反应速度上。

读者页面的主体,显示的是一条又一条短信。不妨把整个页面分割成若干局部,每个局部对应一条短信。所谓 Fragment,就是指页面的局部。除短信外,其它内容例如 Twitter logo 等等,也是 Fragment。如果一个作者拥有众多读者,那么缓存这个作者写的短信的布局页面 (Fragment),就可以提高网站整体的读取效率。这就是 Fragment Cache 的使命。

对于一些人气很旺的作者,读者们不仅会读他写的短信,而且会访问他的主页,所以,也有必要缓存这些人气作者的个人主页。这就是 Page Cache 的使命。

Fragment Cache 和 Page Cache,使用的工具也是 MemCached。

观测实际运行的结果,Fragment Cache 的命中率高达 95%,而 Page Cache 的命中率只有 40%。虽然 Page Cache 的命中率低,但是它的内容是整个个人主页,所以占用的空间却不小。为了防止 Page Cache 争夺 Fragment Cache 的空间,在物理部署时,Twitter 工程师们把 Page Cache 分离到不同的机器上去。

3. HTTP Accelerator

解决了 API 通道的缓存问题,接下去 Twitter 工程师们着手处理 Web 通道的缓存问题。经过分析,他们认为 Web 通道的压力,主要来自于搜索。尤其是面临突发事件时,读者们会搜索相关短信,而不理会这些短信的作者,是不是自己 “追” 的那些作者。

要降低搜索的压力,不妨把搜索关键词,及其对应的搜索结果,缓存起来。Twitter 工程师们使用的缓存工具,是开源项目 Varnish [18]。

比较有趣的事情是,通常把 Varnish 部署在 Web Server 之外,面向 Internet 的位置。这样,当用户访问网站时,实际上先访问 Varnish,读取所需内容。只有在 Varnish 没有缓存相应内容时,用户请求才被转发到 Web Server 上去。而 Twitter 的部署,却是把 Varnish 放在 Apache Web Server 内侧 [19]。原因是 Twitter 的工程师们觉得 Varnish 的操作比较复杂,为了降低 Varnish 崩溃造成整个网站瘫痪的可能性,他们便采取了这种古怪而且保守的部署方式。

Apache Web Server 的主要任务,是解析 HTTP,以及分发任务。不同的 Mongrel Rails Server 负责不同的任务,但是绝大多数 Mongrel Rails Server,都要与 Vector Cache 和 Row Cache 联系,读取数据。Rails Server 如何与 MemCached 联系呢?Twitter 工程师们自行开发了一个 Rails 插件 (Gem),称为 CacheMoney。

虽然 Twitter 没有公开 Varnish 的命中率是多少,但是 [17] 声称,使用了 Varnish 以后,导致整个 Twitter.com 网站的负载下降了 50%,参见 Figure 3.

解剖Twitter 【3】Cache == Cash

Figure 3. Cache decreases Twitter.com load by 50% [17]
Courtesy http://farm3.static.flickr.com/2537/4061273900_2d91c94374_o.png

Reference,

[12] Alphabetical List of Twitter Services and Applications.
(http://en.wikipedia.org/wiki/List_of_Twitter_services_and_applications)
[13] How flash changes the DBMS world.
(http://hansolav.net/blog/content/binary/HowFlashMemory.pdf)
[14] Improving running component of Twitter.
(http://qconlondon.com/london-2009/file?path=/qcon-london-2009/slides/
EvanWeaver_ImprovingRunningComponentsAtTwitter.pdf)
[15] A high-performance, general-purposed, distributed memory object caching system.
(http://www.danga.com/memcached/)
[16] Updating Twitter without service disruptions.
(http://gojko.net/2009/03/16/qcon-london-2009-upgrading-twitter-without-service-disruptions/)
[17] Fixing Twitter. (http://assets.en.oreilly.com/1/event/29/
Fixing_Twitter_Improving_the_Performance_and_Scalability_of_the_World_s_
Most_Popular_Micro-blogging_Site_Presentation%20Presentation.pdf)
[18] Varnish, a high-performance HTTP accelerator.
(http://varnish.projects.linpro.no/)
[19] How to use Varnish in Twitter.com?
(http://projects.linpro.no/pipermail/varnish-dev/2009-February/000968.html)
[20] CacheMoney Gem, an open-source write-through caching library.
(http://github.com/nkallen/cache-money)

登录,参与讨论前请先登录

评论在审核通过后将对所有人可见

正在加载中

移动互联网的围观者、起哄者、以及肇事者。

本篇来自栏目

解锁订阅模式,获得更多专属优质内容