Tumblr:150億月瀏覽量背后的架構挑戰(下)
導讀:和許多新興的網站一樣,著名的輕博客服務 Tumblr 在急速發展中面臨了系統架構的瓶頸。每天 5 億次瀏覽量,峰值每秒 4 萬次請求,每天 3TB 新的數據存儲,超過 1000 臺服務器,這樣的情況下如何保證老系統平穩運行,平穩過渡到新的系統,Tumblr 正面臨巨大的挑戰。近日,HighScalability 網站的 Todd Hoff 采訪了該公司的分布式系統工程師 Blake Matheny,撰文系統介紹了網站的架構,內容很有價值。我們也非常希望國內的公司和團隊多做類似分享,貢獻于社區的同時,更能提升自身的江湖地位,對招聘、業務發展都好處多多。
英文原文:High Scalability
內部的 firehose(通信管道)
- 內部的應用需要活躍的信息流通道。這些信息包括用戶創建/刪除的信息,liking/unliking 的提示,等等。挑戰在于這些數據要實時的分布式處理。我們希望能夠檢測內部運行狀況,應用的生態系統能夠可靠的生長,同時還需要建設分布式系統的控制中心。
- 以前,這些信息是基于 Scribe (非死book 開源的分布式日志系統。)/Hadoop 的分布式系統。服務會先記錄在 Scribe 中,并持續的長尾形式寫入,然后將數據輸送給應用。這種模式可以立即停止伸縮,尤其在峰值時每秒要創建數以千計的信息。不要指望人們會細水長流式的發布文 件和 grep。
- 內部的 firehose 就像裝載著信息的大巴,各種服務和應用通過 Thrift 與消防管線溝通。(一個可伸縮的跨語言的服務開發框架。)
- LinkedIn 的 Kafka 用于存儲信息。內部人員通過 HTTP 鏈接 firehose。經常面對巨大的數據沖擊,采用 MySQL 顯然不是一個好主意,分區實施越來越普遍。
- firehose 的模型是非常靈活的,而不像 推ter 的 firehose 那樣數據被假定是丟失的。
- firehose 的信息流可以及時的回放。他保留一周內的數據,可以調出這期間任何時間點的數據。
- 支持多個客戶端連接,而且不會看到重復的數據。每個客戶端有一個 ID。Kafka 支持客戶群,每個群中的客戶都用同一個 ID,他們不會讀取重復的數據。可以創建多個客戶端使用同一個 ID,而且不會看到重復的數據。這將保證數據的獨立性和并行處理。Kafka 使用 ZooKeeper (Apache 推出的開源分布式應用程序協調服務。)定期檢查用戶閱讀了多少。
為 Dashboard 收件箱設計的 Cell 架構
- 現在支持 Dashboard 的功能的分散-集中架構非常受限,這種狀況不會持續很久。
- 解決方法是采用基于 Cell 架構的收件箱模型,與 非死book Messages 非常相似。
- 收件箱與分散-集中架構是對立的。每一位用戶的 dashboard 都是由其追隨者的發言和行動組成的,并按照時間順序存儲。
- 就因為是收件箱就解決了分散-集中的問題。你可以會問到底在收件箱中放了些什么,讓其如此廉價。這種方式將運行很長時間。
- 重寫 Dashboard 非常困難。數據已經分布,但是用戶局部升級產生的數據交換的質量還沒有完全搞定。
- 數據量是非常驚人的。平均每條消息轉發給上百個不同的用戶,這比 非死book 面對的困難還要大。大數據+高分布率+多個數據中心。
- 每秒鐘上百萬次寫入,5萬次讀取。沒有重復和壓縮的數據增長為2.7TB,每秒百萬次寫入操作來自 24 字節行鍵。
- 已經流行的應用按此方法運行。
- cell
- 每個 cell 是獨立的,并保存著一定數量用戶的全部數據。在用戶的 Dashboard 中顯示的所有數據也在這個 cell 中。
- 用戶映射到 cell。一個數據中心有很多 cell。
- 每個 cell 都有一個 HBase 的集群,服務集群,Redis 的緩存集群。
- 用戶歸屬到 cell,所有 cell 的共同為用戶發言提供支持。
- 每個 cell 都基于 Finagle(推ter 推出的異步的遠程過程調用庫),建設在 HBase 上,Thrift 用于開發與 firehose 和各種請求與數據庫的鏈接。(請糾錯)
- 一個用戶進入 Dashboard,其追隨者歸屬到特定的 cell,這個服務節點通過 HBase 讀取他們的 dashboard 并返回數據。
- 后臺將追隨者的 dashboard 歸入當前用戶的 table,并處理請求。
- Redis 的緩存層用于 cell 內部處理用戶發言。
- 請求流:用戶發布消息,消息將被寫入 firehose,所有的 cell 處理這條消息并把發言文本寫入數據庫,cell 查找是否所有發布消息追隨者都在本 cell 內,如果是的話,所有追隨者的收件箱將更新用戶的 ID。(請糾錯)
- cell 設計的優點:
- 大規模的請求被并行處理,組件相互隔離不會產生干擾。 cell 是一個并行的單位,因此可以任意調整規格以適應用戶群的增長。
- cell 的故障是獨立的。一個 Cell 的故障不會影響其他 cell。
- cell 的表現非常好,能夠進行各種升級測試,實施滾動升級,并測試不同版本的軟件。
- 關鍵的思想是容易遺漏的:所有的發言都是可以復制到所有的 cell。
- 每個 cell 中存儲的所有發言的單一副本。 每個 cell 可以完全滿足 Dashboard 呈現請求。應用不用請求所有發言者的 ID,只需要請求那些用戶的 ID。(“那些用戶”所指不清,請指正。)他可以在 dashboard 返回內容。每一個 cell 都可以滿足 Dashboard 的所有需求,而不需要與其他 cell 進行通信。
- 用到兩個 HBase table :一個 table 用于存儲每個發言的副本,這個 table 相對較小。在 cell 內,這些數據將與存儲每一個發言者 ID。第二個 table 告訴我們用戶的 dashboard 不需要顯示所有的追隨者。當用戶通過不同的終端訪問一個發言,并不代表閱讀了兩次。收件箱模型可以保證你閱讀到。
- 發言并不會直接進入到收件箱,因為那實在太大了。所以,發言者的 ID 將被發送到收件箱,同時發言內容將進入 cell。這個模式有效的減少了存儲需求,只需要返回用戶在收件箱中瀏覽發言的時間。而缺點是每一個 cell 保存所有的發言副本。令人驚奇的是,所有發言比收件箱中的鏡像要小。(請糾錯)每天每個 cell 的發言增長 50GB,收件箱每天增長2.7TB。用戶消耗的資源遠遠超過他們制造的。
- 用戶的 dashboard 不包含發言的內容,只顯示發言者的 ID,主要的增長來自 ID。(請 Tumblr 用戶糾錯)
- 當追隨者改變時,這種設計方案也是安全的。因為所有的發言都保存在 cell 中了。如果只有追隨者的發言保存在 cell 中,那么當追隨者改變了,將需要一些回填工作。
- 另外一種設計方案是采用獨立的發言存儲集群。這種設計的缺點是,如果群集出現故障,它會影響整個網站。因此,使用 cell 的設計以及后復制到所有 cell 的方式,創建了一個非常強大的架構。
- 一個用戶擁有上百萬的追隨者,這帶來非常大的困難,有選擇的處理用戶的追隨者以及他們的存取模式(見 Feeding Frenzy)
- 不同的用戶采用不同并且恰當的存取模式和分布模型,兩個不同的分布模式包括:一個適合受歡迎的用戶,一個使用大眾。
- 依據用戶的類型采用不同的數據處理方式,活躍用戶的發言并不會被真正發布,發言將被有選擇的體現。(果真如此?請 Tumblr 用戶糾錯)
- 追隨了上百萬用戶的用戶,將像擁有上百萬追隨者的用戶那樣對待。
- cell 的大小非常難于決定。cell 的大小直接影響網站的成敗。每個 cell 歸于的用戶數量是影響力之一。需要權衡接受怎樣的用戶體驗,以及為之付出多少投資。
- 從 firehose 中讀取數據將是對網絡最大的考驗。在 cell 內部網絡流量是可管理的。
- 當更多 cell 被增添到網絡中來,他們可以進入到 cell 組中,并從 firehose 中讀取數據。一個分層的數據復制計劃。這可以幫助遷移到多個數據中心。
在紐約啟動運作
- 紐約具有獨特的環境,資金和廣告充足。招聘極具挑戰性,因為缺乏創業經驗。
- 在過去的幾年里,紐約一直致力于推動創業。紐約大學和哥倫比亞大學有一些項目,鼓勵學生到初創企業實習,而不僅僅去華爾街。市長建立了一所學院,側重于技術。
團隊架構
- 團隊:基礎架構,平臺,SRE,產品,web ops,服務;
- 基礎架構:5層以下,IP 地址和 DNS,硬件配置;
- 平臺:核心應用開發,SQL 分片,服務,Web 運營;
- SRE:在平臺和產品之間,側重于解決可靠性和擴展性的燃眉之急;
- 服務團隊:相對而言更具戰略性,
- Web ops:負責問題檢測、響應和優化。
軟件部署
- 開發了一套 rsync 腳本,可以隨處部署 PHP 應用程序。一旦機器的數量超過 200 臺,系統便開始出現問題,部署花費了很長時間才完成,機器處于部署進程中的各種狀態。
- 接下來,使用 Capistrano(一個開源工具,可以在多臺服務器上運行腳本)在服務堆棧中構建部署進程(開發、分期、生產)。在幾十臺機器上部署可以正常工作,但當通過 SSH 部署到數百臺服務器時,再次失敗。
- 現在,所有的機器上運行一個協調軟件。基于 Redhat Func(一個安全的、腳本化的遠程控制框架和接口)功能,一個輕量級的 API 用于向主機發送命令,以構建擴展性。
- 建立部署是在 Func 的基礎上向主機發送命令,避免了使用 SSH。比如,想在組A上部署軟件,控制主機就可以找出隸屬于組A的節點,并運行部署命令。
- 部署命令通過 Capistrano 實施。Func API 可用于返回狀態報告,報告哪些機器上有這些軟件版本。
- 安全重啟任何服務,因為它們會關閉連接,然后重啟。
- 在激活前的黑暗模式下運行所有功能。
展望
- 從哲學上將,任何人都可以使用自己想要的任意工具。但隨著團隊的發展壯大,這些工具出現了問題。新員工想要更好地融入團隊,快速地解決問題,必須以他們為中心,建立操作的標準化。
- 過程類似于 Scrum(一種敏捷管理框架),非常敏捷。
- 每個開發人員都有一臺預配置的開發機器,并按照控制更新。
- 開發機會出現變化,測試,分期,乃至用于生產。
- 開發者使用 VIM 和 TextMate。
- 測試是對 PHP 程序進行代碼審核。
- 在服務方面,他們已經實現了一個與提交相掛鉤的測試基礎架構,接下來將繼承并內建通知機制。
招聘流程
- 面試通常避免數學、猜謎、腦筋急轉彎等問題,而著重關注應聘者在工作中實際要做什么。
- 著重編程技能。
- 面試不是比較,只是要找對的人。
- 挑戰在于找到具有可用性、擴展性經驗的人才,以應對 Tumblr 面臨的網絡擁塞。
- 在 Tumblr 工程博客(Tumblr Engineering Blog),他們對已過世的 Dennis Ritchie 和 John McCarthy 予以紀念。
經驗及教訓
- 自動化無處不在
- MySQL(增加分片)規模,應用程序暫時還不行
- Redis 總能帶給人驚喜
- 基于 Scala 語言的應用執行效率是出色的
- 廢棄項目——當你不確定將如何工作時
- 不顧用在他們發展經歷中沒經歷過技術挑戰的人,聘用有技術實力的人是因為他們能適合你的團隊以及工作。
- 選擇正確的軟件集合將會幫助你找到你需要的人
- 建立團隊的技能
- 閱讀文檔和博客文章。
- 多與同行交流,可以接觸一些領域中經驗豐富的人,例如與在 非死book、推ter、LinkedIn 的工程師多交流,從他們身上可以學到很多
- 對技術要循序漸進,在正式投入使用之前他們煞費苦心的學習 HBase 和 Redis。同時在試點項目中使用或將其控制在有限損害范圍之內。
翻譯:包研,張志平
來自: CSDN
本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!