從Twitter的架構變遷看Web2.0的架構技術
51CTO推薦:視頻專題-大型網(wǎng)站架構技術專家談
Evan Weaver是Twitter服務團隊的總工程師,他的主要工作是優(yōu)化與伸縮性。在一個技術峰會上,他談到了Twitter的架構,特別是在過去一年當中為提升Web站點性能所執(zhí)行的優(yōu)化。
Twitter使用的大部分工具都是開源的。其結構是用Rails作前端,C,Scala和Java組成中間的業(yè)務層,使用MySQL存儲數(shù)據(jù)。所有的東西都保存在RAM里,而數(shù)據(jù)庫只是用作備份。Rails前端處理展現(xiàn),緩存組織,DB查詢以及同步插入。這一前端主要由幾部分客戶服務粘合而成,大部分是C寫的:MySQL客戶端,Memcached客戶端,一個JSON端,以及其它。
中間件使用了Memcached,Varnish用于頁面緩存,一個用Scala寫成的MQ,Kestrel和一個Comet服務器也正在規(guī)劃之中,該服務器也是用Scala寫成,當客戶端想要跟蹤大量的tweet時它就能派上用場。
Twitter是作為一個“內(nèi)容管理平臺而非消息管理平臺”開始的,因此從一開始基于聚合讀取的模型改變到現(xiàn)在的所有用戶都需要更新最新tweet的消息模型,需要許許多多的優(yōu)化。這一改動主要在于三個方面:緩存,MQ以及Memcached客戶端。
緩存
每個tweet平均被126個用戶跟蹤,所以這里有著明顯的緩存需求。在最初的配置中,只有API有著一個,當每次從一個用戶那里來了一個tweet時就會失效,而應用的其它部分都是無緩存的:
第一個架構改動是創(chuàng)建一個直寫式向量緩存包含了一個tweet ID的數(shù)組,tweet ID是序列化的64位整數(shù)。這一緩存的命中率是99%。
第二個架構改動是加入另一個直寫式行緩存,它包含了數(shù)據(jù)庫記錄:用戶和tweets。這一緩存有著95%的命中率并且使用了Nick Kallen的名為Cache Money的Rails插件。Nick是Twitter的一名系統(tǒng)架構師。
第三個架構改動是引入了一個直讀式的碎片緩存,它包含了通過API客戶端訪問到的tweets的序列化版本,這些tweets可以被打包成JSON,XML或者是Atom的格式,有著同樣是95%的命中率。這一碎片緩存“直接消費向量,而且如果現(xiàn)在緩存了一個序列化的碎片,它不會加載你試圖看到的該tweet的實際的行,因此它將在大量時間將數(shù)據(jù)庫置于短路狀態(tài),”Evan這樣說到。
還有另一個改動是為頁面緩存創(chuàng)建一個單獨的緩存池。根據(jù)Evan的說法,該頁面緩存池使用了一個分代的鍵模式,而不是直接的失效,因為用戶可以發(fā)送HTTP的if-modified-since并且將任何他們想要的時間戳放入請求路徑,我們需要將這一數(shù)組切片并只呈現(xiàn)給他們他們想要看到的tweets,但我們不想跟蹤客戶端所使用的所有可能的鍵值。這一分代的鍵模式有一個大問題,在于它不會刪除所有失效的鍵值。每一個被加入的對應到人們所接收的tweets數(shù)目的頁面都會向緩存推送有效的數(shù)據(jù),最后變得我們的緩存僅僅只有五個小時的有效生命周期,因為所有的頁面緩存都將流過。
當該頁面緩存轉移到其自己的池之后,緩存未命中降低了將近50%。
這是Twitter現(xiàn)在所使用的緩存模式:
因為80%的Twitter流量都來自API,因此還有額外的二層緩存,每一個最多將處理95%來自前一層的請求。整體的緩存改動總共有百分之二三十的優(yōu)化,它帶來了
10倍的容量提升,它本可以更多,但現(xiàn)在我們遇到了另一瓶頸...我們的策略是首先加入直讀式緩存,確保它正確失效,然后再轉移到直寫式緩存并且在線修復,而不是當一個新的tweet ID進來時每次都要銷毀。
消息隊列
因為,平均來說一個用戶有126個追隨者,這就意味著每個tweet將有126個消息在隊列里。同時,流量會有出現(xiàn)高峰的時候,就像在奧巴馬就職的時候達到了每秒幾百個tweet或者說是成千上萬的消息在隊列里,是正常流量的3倍。MQ應當去化解這一高峰并隨著時間將其分散,這樣就不用增加許多額外的硬件。Twitter的MQ很簡單:基于Memcached的協(xié)議,job之間是無序的,服務器之間沒有共享的狀態(tài),所有的東西都保存在RAM里,并且是事務性的。
第一版的MQ實現(xiàn)是用的Starling,以Ruby寫成,伸縮性不佳,特別是Ruby的GC不是分代的。這將導致MQ在某一點上崩潰,因為GC完成工作時將會把整個隊列處理中止。因此作出了將MQ移植到Scala上的決定,它有著更為成熟的JVM GC機制?,F(xiàn)有的MQ僅僅只有1200行代碼并且運行在3臺服務器上。
Memcached客戶端
Memcached客戶端的優(yōu)化目的是試圖優(yōu)化集群負載?,F(xiàn)在的客戶端用的是libmemcached,Twitter是其最重要的用戶和其代碼庫最重要的貢獻者?;诖耍掷m(xù)一年的碎片緩存優(yōu)化帶來了50倍的每秒頁面請求服務增加。
因為請求來自的位置難以確定,處理請求最快的辦法就是將預先計算好的數(shù)據(jù)存儲在網(wǎng)絡RAM上,而不是當需要的時候在每個服務器上都重新計算一次。這一方式被主流的Web 2.0站點所使用,它們幾乎都是完全直接運行于內(nèi)存之上。根據(jù)Evan的說法,下一步就是“既可伸縮的讀持續(xù)了一年之后,(解決)可伸縮的寫,然后就是多協(xié)同定位的問題”。
【編輯推薦】


















 
 
 







 
 
 
 