Tumblr的架構設計

隨着每月頁面瀏覽量突破15億次,Tumblr已經名正言順地躋身博客類平臺中的名人堂。用戶們對它的簡潔、美觀以及對使用體驗的專注追求讚不絕口;它的相關社區也同樣氛圍溫馨、人氣爆棚。總之,人們喜歡這位博客家族中的新貴。

超過30%的月度增長不可能一帆風順,過程中的坎坷與挑戰也自然不言而喻,但最令人頭痛的還是可靠性問題。正是經過技術人員的不懈努力,Tumblr才取得了如此驚人的規模及傲人的運行成績:每天5億次頁面瀏覽、每秒四萬次查詢請求峯值、每天新數據存儲量高達約3TB、總支持服務器達到1000餘臺。

大多數成功的新興企業都面臨着相似的困擾,由於從初來乍到的新成員一躍成爲萬衆矚目的焦點角色,一道巨大的危險鴻溝硬生生將原本孱弱的技術支持團隊 推向了風口浪尖。招聘員工、擴大基礎設施、維護舊有基礎設施的同時,仍然只有寥寥數位工程師負責着每個月巨大的數據吞吐量。這樣的工作強度意味着我們在處 理過程中必須有所側重,而做出這樣的選擇無疑相當艱難。Tumblr目前也陷入了這樣的困境,他們的做法是創建起一個由二十位精力充沛的工程師組成的技術小組,在應對日常事務的同時制訂出多種極富創意的解決方案。

Tumblr創立之初就將自己定位爲典型的大型LAMP(即由定製組件構成的系統)應用程序。如今他們前進的方向是通過Scala、HBase、Redis、Kafka、Finagle以及以架構爲基礎的新穎單元共同打造出多種分佈式服務模塊,藉以構成完整的Dashboard導航內容。目前他們已經開始嘗試修復PHP應用程序中的短期問題、將故障部分抽離出來並利用服務機制進行更正。

Tumblr發展的主題是在龐大的平臺規模之上實施成功轉型。即將LAMP堆棧轉變爲一套更具突破性特性的新堆棧,同時將原本適用於新興企業的小型 團隊擴展爲裝備精良、擅長開發工作的成熟團隊,進而爲用戶帶來大量新功能及基礎設施。爲了幫助我們更透徹地理解Tumblr實現這一方針的具體做 法,Tumblr公司分佈式系統工程師Blake Matheny分享了他的心得體會。以下是Blake對Tumblr做出的信息彙總:

Tumblr官方網址:http://www.tumblr.com/

統計

  • 每天5億次頁面瀏覽量
  • 每月15億次以上頁面瀏覽量
  • 約20位技術工程師
  • 每秒4萬次查詢請求峯值
  • Hadoop集羣每天接受超過1TB的數據量
  • MySQL/HBase/Redis/Memcache等系統每天需要處理數以TB計的信息
  • 每月用戶數量及處理負載增長30%
  • 日常運行中涉及約1000個硬件節點
  • 每個月每位工程師平均要面對上億次頁面訪問活動
  • 每天新增的博文及帖子約爲50GB。新的用戶關注列表每天帶來約2.7TB的數據存儲量
  • Dashboard系統每秒要應對百萬次寫入操作、5萬次讀取操作,這一數字還在不斷增長之中

軟件

  • 開發工作在OS X上進行,日常運行則交給Linux系統(CentOS、Scientific)
  • Apache
  • PHP, Scala, Ruby
  • Redis, HBase, MySQL
  • Varnish, HA-Proxy, nginx,
  • Memcache, Gearman, Kafka, Kestrel, Finagle
  • Thrift, HTTP
  • Func - 一款安全且腳本化良好的遠程控制框架及API
  • Git, Capistrano, Puppet, Jenkins

硬件

  • 500 臺web服務器
  • 200臺數據庫服務器(其中大多數作爲故障發生時的後備資源存在)
    • 47個資源池
    • 30個區塊
  • 30臺緩存服務器
  • 22 臺redis服務器
  • 15 臺varnish服務器
  • 25個haproxy節點
  • 8 個nginx反向代理服務器
  • 14臺作業隊列服務器(kestrel+gearman)

架構

  • 比起其它社交型網絡,Tumblr擁有一套完全不同的使用模式。
    • 每天有五千多萬篇博文發表,每一篇都有數百次的平均瀏覽量。並不是說少數熱門用戶具備的數百萬關注者拉昇了平均瀏覽量,事實上每位Tumblr用 戶基本都有成百上千的關注者。這與以往任何類型的社交網絡都有所不同,也恰恰是這種特性讓Tumblr面臨着史無前例的規模化考驗。
    • Tumblr目前是用戶傾注時間第二多的熱門社交網絡,其內容也極具吸引力。由於允許用戶自由分享圖片與視頻,因此博文的體積不再以字節計算。盡 管用戶不一定總會發布體積龐大的內容,但網站保證每個人都在需要時具備豐富自己文章的能力。人們樂於撰寫更爲深刻的主題,這也讓關注者們找到了閱讀的樂 趣,並持續花費大量時間訪問Tumblr。
    • 用戶之間構成一套完整的聯絡紐帶,因此他們常常會嘗試回溯Dashboard中數百頁之前的內容。其它社交網絡則往往只提供信息流,用戶體驗只停留在驚鴻一瞥的層面上。
    • 也就是說,由於用戶數量之大、每位用戶的平均閱讀數量之多以及用戶發起各類活動積極性之高,Tumblr需要處理的上傳信息龐大到令人驚愕。
  • Tumblr運行於一套託管站點中。設計者們爲網站留出了充分的地理分佈空間,以應對未來的發展需求。
  • Tumblr平臺由兩大組件構成:Public Tumblelog與Dashboard系統。
    • Public Tumblelog 是一款面向公衆的博客。由於動態特性較弱,因此緩存更易於打理。
    • Dashboard在功能上與Twitter的timeline頗爲相近。用戶將實時接收到自己關注對象的更新信息。
      • 在規模特性上與其它博客載體頗爲不同。緩存在這裏的作用不再明顯,因爲每條請求都各不相同,尤其是對於那些活躍的關注者而言。
      • 運行中必須保持高度的實時性與一致性,不應顯示陳舊數據,且需要處理的數據量非常龐大。每天的博文內容本身只有50GB,但關注者列表更新信息則高達2.7TB。媒體文件全部存儲於內存中。
  • 大多數用戶將Tumblr作爲內容型消費工具。每天頁面瀏覽量超過5億次,70%的瀏覽行爲針對Dashboard系統。
  • Dashboard系統的可用性相當值得稱道。Tumblelog則一直有所欠缺,因爲其中的某套原有基礎設施目前很難實施遷移。鑑於技術支持團隊的規模太小,他們不得不在規模化進程中優先處理那些時間短、見效快的內容。

過去的Tumblr

  • Tumblr起初立足於Rackspace公司,後者爲每個自定義域名博客創建一套A記錄。到了2007年,他們已經擁有極爲龐大的用戶羣體,爲 了實施整體遷移,他們開始嘗試獨立於Rackspace公司之外。這時他們的自定義域業務仍然由Rackspace負責,爲了保持用戶的訪問方式,他們利 用HAProxy與Varnish代理服務器將Rackspace域名轉向自己的服務器空間。類似的歷史遺留問題還有很多。
  • 一套傳統的LAMP。
    • 一直使用PHP,幾乎每位工程師都通過PHP處理編程工作。
    • 創立之初只擁有一臺web服務器、一臺數據庫服務器以及一套PHP應用程序。
    • 爲了完成規模化擴展,他們開始使用memcache,接着引入前端緩存,然後是將HAProxy置於緩存之前,最後採用MySQL分區。MySQL分區體系的加入使整體服務效果邁上新的臺階。
    • 力圖將所有處理負載控制在一臺服務器的承受能力之內。在過去的一年中,他們藉助C語言開發出兩款後端服務:ID生成器Staircar,Dashboard通知功能則利用Redis實現。
  • Dashboard採用分散-集中式處理方案,當用戶訪問Dashboard時事件將自動予以顯示。而讓用戶關注對象的新事件以推送形式顯示又花了技術團隊六個月的時間。由於數據以時間爲標準排序,因此分區設計方案的表現並不盡如人意。

如今的Tumblr

  • 出於提高租用及開發速度的考量,如今採用JVM中央方案。
  • 目標是將所有存在於PHP應用中的內容遷移至服務項目中,並將PHP應用本身作爲新建的層置於服務之上,用於負責請求驗證及介紹說明等工作。
  • 選擇使用Scala與Finagle。
    • 公司內部擁有大量擅長Ruby及PHP開發工作的成員,因此Scala的推廣也就更爲輕鬆。
    • Finagle的使用也是他們選擇Scala的重要原因之一。這是一套來自Twitter的庫,能夠處理大多數由分佈式設施帶來的技術難題,包括分佈式跟蹤、服務項目搜索以及服務項目註冊等。當然這些功能我們也不必全部採用,根據實際需求選擇即可,反正都是免費的。
    • 一旦與JVM環境相結合,Finagle能夠提供他們所需要的一切基本要素(例如Thrift、ZooKeeper等等)。
    • Foursquare及Twitter一直在使用Finagle,Scala也始終效力於Meetup網站。
    • 與Thrift應用程序接口一樣,Finagle也帶來了相當優異的性能表現。
    • 希望得到像Netty那樣的運行效果,又不想涉及Java,因此Scala是最好的選擇。
    • 採用Finagle是因爲它功能強勁、所需知識並不冷門,使用中不涉及過多網絡代碼而且能爲分佈式系統提供一切所需功能。
    • Node.js沒有入選的原因在於,它在JVM環境下對於技術團隊的規模要求比較高。Node.js在開發方面缺乏標準化及最佳實踐選項,測試用 代碼也相對較少。而Scala允許我們使用任何現有Java代碼。而且在不要求過多知識儲備的基礎上,Scala能夠輕鬆應對未來可能出現的擴展性要求, 同時保障5毫秒響應時間、49秒雙機集羣切換以及平均每秒四萬次、峯值四十萬次的請求處理。同時Java體系中的大量資源也可爲我們所用。
  • 內部服務項目正由以C語言/libevent函式庫爲基礎向Scala/Finagle爲基礎轉變。
  • 採用更新的HBase以及Redis等非關係類數據存儲機制,但目前大多數數據存儲在一套高度分區下的MySQL架構中。尚沒有用HBase徹底替代MySQL。
  • HBase憑藉數以億計的URL以及全部歷史數據與分析結果支持自身的URL簡寫功能,運行表現一直穩固可靠。HBase主要用於處理高寫入請求 情況,例如每秒上百萬次寫入動作的Dashboard重置操作。HBase沒有被用來替代MySQL的原因在於,Tumblr目前的技術支持團隊尚無法在 HBase上完成全部業務需求,因此他們最終決定先在規模較小的非關鍵性項目上進行試用,儘量積累使用經驗。
  • 以MySQL及分區機制爲基礎,將按時間排序的所有數據納入同一個分區的過程始終麻煩不斷。讀取及複製操作也由於子集羣寫入動作的同時發生而常常出現滯後現象。
  • 創建出一套通用型服務框架。
    • 事先花費大量時間制訂方案,用以解決分佈式系統在管理時出現的操作問題。
    • 創建一套用於服務項目的Rails橋架,作爲引導內部服務的模板使用。
    • 所有服務項目從運行的角度來看都完全一致。各服務的狀態檢查、監控、啓用以及中止都以同樣的方式進行。
    • 創建過程中使用的工具爲SBT(一款Scala創建工具),同時用到的還有其它一些插件及輔助內容,旨在爲包括git項目標註、倉庫信息發佈等公共活動提供支持。大多數開發人員不必深入瞭解系統的創建過程。
  • 前端層使用HAProxy,Varnish則服務於公共博客,二者共計佔用40臺設備。
  • Apache及各類PHP應用程序由500臺網絡服務器予以支持。
  • 數據庫服務器共有200臺。大部分數據庫服務器用於提高整體可用性。由於使用標準化硬件配置,因此平均無故障工作時間相當令人滿意。硬件設備的損耗大大超出預期,因此技術人員準備了大量後備物資以應對不時之需。
  • 六項用於支持PHP應用程序的後端服務。一個專項小組專門負責開發此類後端服務。每隔兩到三週都會有一款新服務推出,例如Dashboard通知、Dashboard輔助索引、URL簡寫工具以及用於分區處理的緩存代理器等。
  • 在MySQL分區方面投入大量時間以及人力物力。儘管MongoDB目前在紐約(Tumblr的總部所在地)風靡一時,但他們仍然採用了擴展性更好的MySQL。
  • Gearman,一款作業隊列系統,被用於處理運行時間較長且無人照看的工作內容。
  • 可用性評估以實際使用效果爲標準。用戶能夠正常訪問自定義域名或是Dashboard嗎?另外故障率也是評估中的一項因素。
  • 就長期運行狀況來看,具備最高優先級的項目必須首先得到修復。目前故障模式已經得到有效的分析與系統性解決,其目的是同時從用戶及應用程序的角度來評估整體運行狀態。如果一條請求中的某部分沒有得到充分響應,那麼這套評估機制必須迅速查明原因。
  • 最初的角色模式是由Finagle負責支持的,但後來這種方式被棄之不用,取而代之的是一套無需照看的作業隊列。另外,Twitter的實用庫中 包含一套名爲Futures的服務實施方案。當某個線程池需要被調用時,Futures服務將立即建立一個future池,這時所有待處理內容都將被提交 至future池中以進行異步執行。
  • 由於自身特性的原因,Scala並不適合處理共享狀態。Finagle則可以默認爲適合處理此類情況,因爲Twitter已經將付諸實際應用。在 Scala及Finagle中都應儘量避免可變狀態調用架構的情況。不能讓設備長期處於運行狀態。狀態信息採集自數據庫,並在使用後重新寫入數據庫。這麼 做的優勢是,開發人員們不必擔心線程或者鎖定問題。
  • 22臺Redis服務器。每臺服務器運行8到32個實例,也就是說共計有數百個Redis實例用於生產流程。
    • 後端存儲機制用於爲Dashboard通知功能提供支持。
    • 通知功能本身類似於關注我們博文的某位用戶。通知會顯示在用戶的Dashboard中,這樣我們就能及時瞭解其它用戶的最新動態。
    • 極高的寫入頻率使得MySQL有些力不從心。
    • 通知內容無需長期存在,因此即使用戶掉線也不會出現突然涌入大量提示消息的窘境,這樣一來Redis就成爲實現通知功能的選擇之一。
    • 儘量爲技術人員創造機會,讓他們學習Redis的相關知識並熟悉其工作原理。
    • 由於Redis擁有強大的社區體系,因此無論遇上什麼問題都能在這裏找到解決方法。
    • 爲Redis創建一個以Scala futures爲基礎的接口,這項功能現在正逐漸轉到Cell架構當中。
    • URL簡寫工具將Redis作爲一級緩存,並把HBase當成長效存儲機制。
    • Dashboard的輔助索引圍繞Redis進行創建。
    • Redis作爲Gearman的持久化層存在,並用到了由Finagle創建的緩存代理器。
    • 慢慢由緩存向Redis遷移。希望能夠以一套快取服務作爲最終方案,其性能表現應與緩存方案一致。

內部傳輸線

內部應用程序需要訪問活動流。每個活動流的內容都與用戶行爲相關,例如創建、刪除博文或者喜歡、反感某些博文等。挑戰在於如何將這樣規模的數據實時 加以分散。要達到這一目的,需要足以支持大規模內部擴展的工具以及擁有可靠生態系統輔助的應用程序。此外還要確立分佈式系統的中心點。

  • 之前信息的分佈化由Scribe/Hadoop負責。服務項目要首先登入Scribe並開始追蹤,然後將數據傳輸至應用程序端。這種模式讓可擴展性成爲空談,尤其是在用戶每秒創建上千篇博文的峯值時段。應該儘量避免用戶追蹤文件並進行打印。
  • 創建一套類似於信息公交車這樣的內部傳輸線,服務項目與應用程序通過Thrift與傳輸線進行交互。
  • 利用來自LinkedIn網站的Kafka來存儲消息。內部用戶使用HTTP流直接從傳輸線上閱讀內容。不使用MySQL的原因在於,分區工作本身就過於頻繁,因此不適合讓其承擔大量數據流。
  • Tumblr的傳輸線模式靈活性極強,Twitter所使用的傳輸線則相形見絀,其中的數據常常面臨丟失。
    • 傳輸線流能夠及時進行回溯,它會保存一週以內的所有數據。在連接時,它可以正確找回最後一次閱讀的位置。
    • 允許同時連入多個客戶端,而且每個客戶端所看到的內容都各不相同。每個客戶端擁有獨立的客戶端ID,這要歸功於Kafka所支持的用戶組概念。用 戶組中的每一個用戶不僅會看到與自己相關的消息,並且消息內容絕不重複。可以利用同一個用戶ID創建多個客戶端,這些客戶端所看到的內容同樣不會重複。也 就是說數據以獨立且並行的方式進行處理。Kafka通過ZooKeeper定期爲用戶設置檢查點,以記錄用戶的當前閱讀進度。

Dashboard收件箱的Cell設計

  • 目前爲Dashboard功能提供支持的分散-集中模式存在着一定侷限性,不久之後就會轉而採用更先進的方案。
    • 解決方案是讓收件箱採用以Cell爲基礎的新型架構,這與Facebook的Messages功能頗爲相似。
    • 收件箱可以說是分散-集中模式的對立面。由關注者的博文及近期動態所構成的Dashboard版面,按時間順序及邏輯方式存儲在一起。
    • 由於收件箱的功能特性,分散-集中模式帶來的問題在這裏不攻自破。我們只會詢問收件箱中保存着哪些內容,這完全不涉及關注者、用戶好友之類亂七八糟的關係。這樣的情況將持續很長一段時間。
  • 對Dashboard內容進行重寫是相當困難的。雖然數據擁有分佈式特性,但它同時也擁有交互式特性,因此用戶無法實現局部更新功能。
    • 數據總量之大簡直超乎想象。每一條消息平均要發送給成百上千位不同用戶,這比Facebook的工作負擔更重。大量數據加上高分佈率再加上多個數據中心協同運作,整個流程的複雜程度由此可見一斑。
    • 每秒百萬次寫入操作及五萬次讀取操作,這麼高強度的交互活動帶來了高達2.7TB的數據集增長量,還不算複製或是壓縮等處理工作。由24個字節構成的百萬次寫入操作給收件箱帶來海量信息。
    • 以上所有工作由一套應用程序負責,因此保證程序的正常運作就顯得至關重要。
  • Cell單元。
    • 每個Cell單元都是一套獨立的裝置,其中包含了大量用戶的全部相關數據。用戶Dashboard版面所需要的一切數據都由Cell單元提供。
    • 用戶以映射的方式與Cell單元連通,每個數據中心都運行着大量Cell單元。
    • 每個Cell單元都擁有自己的一套HBase集羣、服務集羣以及Redis緩存集羣。
    • 用戶與Cell單元相對應,所有Cell單元都通過傳輸線中的上傳數據調用博客信息。
    • 每個Cell單元都以Finagle爲基礎,並通過傳輸線以及Thrift上的服務請求構成HBase數據信息。
    • 當某位用戶進入Dashboard版面,就會從特定Cell單元中調出多個相關用戶的信息;服務器節點通過HBase讀取相關用戶的Dashboard內容並將數據傳回當前登錄用戶。
    • 後臺任務從傳輸線中獲取信息,並生成對應列表及處理請求。
    • Cell單元中的博客信息會調用Redis緩存層。
  • 請求指令流:當某位用戶發佈博文,該篇博文即會被寫入傳輸線;所有Cell單元從中讀取博文內容並將其轉寫入文章數據庫中;接着Cell單元會檢查該文用戶的關注者中有哪些處於自身單元內部,最終將尋獲的關注者收件箱以及博文ID共同進行上傳。
  • Cell單元設計的優勢所在:
    • 請求指令的大量同時出現勢必對並行處理能力要求極高,這就使得設備組件必須彼此獨立,然而獨立性也會導致交互過程無法完成。Cell單元設計使並行處理工作成爲一個獨立體系內部的事務,並能夠在用戶羣體不斷增長的情況下隨時保持強大的可調節能力。
    • Cell單元天然具備故障隔離能力。某個Cell單元出錯不會對其它單元造成任何嚴重影響。
    • Cell單元使更新內容測試、信息發佈以及軟件版本測試工作得以有條不紊地進行。
  • 容易被大家忽略的關鍵性環節是:所有文章都會被複制到每一個Cell單元中去。
    • 每個Cell單元都存儲着一套獨立的全局文章副本。每個Cell單元都能夠爲Dashboard版面提供令人滿意的內容。應用程序並不會查詢所有 文章ID,它只會爲登錄ID查詢相關文章,這樣一來用戶將能夠在自己的Dashboard版面中看到所有信息。每一個Cell單元都擁有填充 Dashboard所必需的全部數據,因此不必進行什麼跨單元通訊。
    • 共使用了兩套HBase列表:一套用於存儲文章副本,而另一套則爲Cell單元中的每個用戶保存博文ID,列表之間的內容基本無甚關聯。第二套列 表的作用是爲用戶的Dashboard版面提供顯示內容,也就是說不必追蹤該用戶所關注的每位其它用戶。另外,利用這種機制,如果我們在另一臺設備上閱讀 或瀏覽某篇文章,系統將不會認爲我們是在重複讀取同樣的內容。無論通過何種方式,我們的閱讀進度都將保存在收件箱模塊的狀態一項中。
    • 文章不會被直接置於收件箱中,因爲這麼多文章累積起來容量實在驚人。因此只將ID放入收件箱,而文章內容則由Cell單元保存。這種方式大幅度降 低了所需存儲空間,並讓用戶收件箱中的內容按時間順序變得非常簡便。這麼做的缺點是每個Cell單元都需要包含完整的文章副本。但令人驚訝的是,文章本身 的體積總量遠遠小於映射所需的存儲空間。每天每個Cell單元中的文章內容增量約爲50GB,但收件箱內容的增量卻高達每天2.7TB。由此可見,用戶的 閱讀量比寫入量大得多。
    • 用戶的Dashboard中並不顯示文章內容,只包含基本的文章ID;因此數據增量的主體是不斷膨脹的ID。
    • 即使用戶的關注者名單發生變更,這種設計仍然完全應付得來,因爲所有文章都已經存在於Cell單元中。如果Cell單元中只保存來自關注者的文章,那麼一旦關注者名單有所變動,單元中的數據將不足以及時做出反應,同時將引發一系列不可避免的信息填充活動。
    • 另有一套備選方案,利用一套獨立的文章集羣存儲博文內容。這種設計的缺點在於,一旦這套集羣出現故障,那麼整個網站都將陷入癱瘓。相比之下,採用Cell單元設計、將所有文章複製到每一個單元當中的做法使整個架構牢固而可靠。
  • 對於那些關注人數以百萬計且相當活躍的用戶,會根據他們的訪問模式獲得特定的用戶服務。
    • 不同的用戶往往使用不同的訪問模式以及與個人習慣相符的分佈模式。Tumblr爲用戶準備了兩種不同的分佈模式:一種適合人氣超高的熱門用戶、另一種則適合任何類型的用戶。
    • 數據的處理方式也根據用戶類型的變化而有所不同。來自活躍用戶的文章實際上不會真正予以發佈,而只是有選擇地呈現給其他用戶。
    • Tumblr在處理大量關注其他使用者的用戶時,採用的方法與處理擁有大量關注者的用戶非常類似。
  • 每個Cell單元的大小很難確定。單元的大小會影響到網站的故障機率,而單元中所包含用戶的數量則是最關鍵的因素。需要在用戶的使用期望與支撐這種期望的成本支出之間找到一個平衡點。
  • 從傳輸線中讀取信息是網絡問題的核心內容。在Cell單元內部,網絡流量始終處於可管理的狀態。
  • 由於Cell單元的數量日益增加,最終Cell單元組的概念被添加進來。這是一套分層複製規劃,同時也有利於將數據信息遷移到多個數據中心當中。

成爲一顆立足於紐約的耀眼新星

  • 紐約的環境背景相當特殊,其中充斥着大量財務與廣告因素。作爲一家缺乏經驗的新興企業,Tumblr在人才招聘及設備租用方面都面臨着挑戰。
  • 在過去幾年中,紐約市一直致力於扶植新興企業。紐約大學與哥倫比亞大學制訂了完善的計劃,鼓勵在校學生到新興企業中去實習,而不是一頭扎進華爾街。Bloomberg市長也將支持科技發展作爲紐約市的一項基本戰略。

團隊構成

  • 團隊:基礎設施、平臺、SRE(即系統調整及修復)、產品、網絡運行以及服務支持。
  • 基礎設施:5層及以下。IP地址及以下、DNS、硬件供應。
  • 平臺:核心應用程序開發、SQL分區、服務、網絡運行。
  • SRE: 存在於服務團隊與網絡運行團隊之間,致力於解決迫在眉睫的系統可靠性及可擴展性問題。
  • 服務團隊:致力於發展戰略層面的問題,處理週期一般爲一到兩個月。
  • 網絡運行:負責問題檢測與響應以及相關調整工作。

軟件開發

  • 一切工作以一套專門將PHP應用程序分佈到各處的rsync腳本集合爲基礎。一旦設備總數達到200臺,系統就會發生故障——部署流程無比緩慢、設備自身也停滯在各種各樣的配置狀態中。
  • 在此之後,Tumblr決定將部署流程(包括開發、啓用及生產等環節)利用Capistrano創建在服務堆棧中。這在數十臺設備協作的情況下沒有問題,但通過SSH讓數百臺設備彼此連接後,問題再一次出現。
  • 現在所有設備上都運行着一套調整軟件,這套軟件以紅帽Func爲基礎,本質上是一個用於將指令分配到各主機處的輕量型API。規模化要素也被部署在Func內部。
  • 開發工作在Func層面上進行,並採用“在某個主機組上執行某操作”的直觀表述,這就成功迴避了對SSH的依賴。例如我們希望在A組中部署軟件,那麼管理員只需選定目標節點集合並運行部署指令,即可完成任務。
  • 部署指令通過Capistrano進行實施,並能夠以git檢查或者倉庫輸出的形式生效。擴展性方面也有所保障,因爲指令面向的交互對象爲 HTTP。之所以採用Capistrano,是因爲它能在良好的版本控制之下支持簡單目錄,這種特性使其與PHP應用程序之間的配合更爲默契。以版本控制 更新活動使得每個目錄都包含安全散列算法,這樣技術人員也能夠方便地核對當前版本是否正確。
  • Func API的作用是回饋狀態,通知系統哪些設備正在運行哪些版本的軟件。
  • 任何服務項目都能夠安全地加以重啓,因爲默認狀態下項目將首先逐漸斷開連接、之後才實施重啓動作。
  • 每項功能在投付使用之前,都會在獨立環境下進行測試。

開發工作

  • Tumblr所秉承的理論是讓每位用戶都能使用自己想要的工具,但隨着用戶羣體的激增,這種想法實在難以爲繼。招聘精明強幹的技術人員不是件容易 的事,因此他們開始對堆棧進行標準化改造,旨在讓技術工作更好上手、團隊培養更加高效、產品問題的處理更加迅速並在上述內容的基礎上建立業務運作。
  • 整個開發過程與Scrum比較相似。選擇的是工作量較小的輕量級模式。
  • 每位開發人員都擁有一臺經過預先配置的開發專用設備。設備更新工作則通過Puppet實現。
  • 開發用設備可以隨時回收並進行變更及測試,接着重新投入使用並最終執行生產任務。
  • 開發人員們常用的文本編輯器是Vim和Textmate。
  • PHP應用程序的測試以代碼審覈的方式進行。
  • 他們在服務項目端部署了一套測試用基礎設施,其中包括hooks、Jenkins以及連續性集成與通行創建系統。

招聘流程

  • 面試階段一般不會涉及數學、分析以及腦力測驗。提出的問題主要圍繞着求職者所申請的職位展開。他們是否聰慧?能否順利完成份內的工作?但評估求職者能否“順利完成份內工作”有一定難度。總之面試的目的是找出身負才能的新人,而不是有意排除一定比例的求職者。
  • 編碼能力是考覈的一大重點。他們會針對示例代碼提出問題,在電話面試的過程中也常常利用Collabedit考驗求職者的共享代碼編寫能力。
  • 面試本身並不具有對抗性,他們只是在嘗試發現優秀的人才。求職者們可以在面試中使用像谷歌這樣的輔助工具來解決問題,因爲Tumblr相信善於使用外界助力的開發人員纔是能夠獨當一面的上上之選,所以在考覈中並不禁止使用輔助手段。
  • 鑑於Tumblr所要應對的數據流量相當巨大,因此招徠在規模化業務方面具備豐富經驗的人才正是當務之急。事實上在全球範圍內,還沒有幾家企業需要處理如此規模的日常工作。
    • 舉例來說,他們需要一款新的ID生成器,要求服務運行環境爲JVM,在每秒一萬條請求的使用頻率下保證響應時間低於1毫秒,並且要在內存限定爲 500MB的前提下保證高可用性。結果在招聘過程中,他們發現了幾位牛人,不僅嚴格按照給定條件執行、還將響應延遲降低到新的水平。這也最終使得 Tumblr願意花費大量時間對JVM運行環境進行調整。
  • 在Tumblr的工程博客中,他們專門發表文章對Dennis Ritchie與John McCarthy表示敬意及紀念,這正是公司極客氛圍的實際體現。

經驗教訓

  • 自動化流程無處不在。
  • MySQL(與分區機制)具備可擴展性,而應用程序本身則不行。
  • Redis功能驚人。
  • Scala應用程序的性能表現令人讚歎。
  • 在不確定某個項目能否起效時,果斷加以廢除。
  • 不要過分在意那些在垃圾技術領域殘喘多年積累到的所謂經驗。真正重要的是他們是否適合自己的團隊、是否能勝任新的工作崗位。
  • 選擇一套能幫你僱用到所需人才的招聘機制。
  • 根據技術團隊的實際狀況定製招聘標準。
  • 儘量多讀些技術論文以及博客文章。像Cell單元架構以及選擇性呈現這樣的好點子往往並非原創。
  • 多與同事們交流。他們中肯定有人會與來自Facebook、Twitter、LinkedIn等網站的工程師們探討工作經歷並學習新知識。我們自己可能還沒有達到同樣的高度,但處處留心絕對有利無弊。
  • 另外,別讓新人直接負責技術工作。在接觸實際生產流程之前,他們需要在試驗性項目組或者工作壓力較小的職位上好好拿出時間學習HBase以及Redis。

在這裏我要向Blake表示感謝,也正是由於他的耐心配合,這篇彙總型文章纔會與大家見面。採訪過程中他表現出令人稱道的慷慨心態,並且不厭其煩地向我們解釋工作流程中的具體細節。

原文:Tumblr Architecture – 15 Billion Page Views a Month and Harder to Scale than Twitter


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章