揭秘 Twitter 背後的基礎設施:效率與優化篇
過去我們曾經發布過一些關於 Finagle 、Manhattan 這些項目的文章,還寫過一些針對大型事件活動的架構優化的文章,例如天空之城、超級碗、2014 世界杯、全球新年夜慶祝活動等。在這篇基礎設施係列文章中,我主要聚焦於 Twitter 的一些關鍵設施和組件。我也會寫一些我們在係統的擴展性、可靠性、效率方麵的做過的改進,例如我們基礎設施的曆史,遇到過的挑戰,學到的教訓,做過的升級,以及我們現在前進的方向等等。
天空之城:2013 年 8 月 2 日,宮崎駿的《天空之城Castle in the Sky》在 NTV 迎來其第 14 次電視重播,劇情發展到高潮之時,Twitter 的 TPS(Tweets Per Second)也被推上了新的高度——143,199 TPS,是平均值的 25 倍,這個記錄保持至今。-- LCTT 譯注
數據中心的效率優化
曆史
當前 Twitter 硬件和數據中心的規模已經超過大多數公司。但達到這樣的規模不是一蹴而就的,係統是隨著軟硬件的升級優化一步步成熟起來的,過程中我們也曾經犯過很多錯誤。
有個一時期我們的係統故障不斷。軟件問題、硬件問題,甚至底層設備問題不斷爆發,常常導致係統運營中斷。出現故障的地方存在於各個方麵,必須綜合考慮才能確定其風險和受到影響的服務。隨著 Twitter 在客戶、服務、媒體上的影響力不斷擴大,構建一個高效、可靠的係統來提供服務成為我們的戰略訴求。
Twitter係統故障的界麵被稱為失敗鯨Fail Whale,如下圖 -- LCTT 譯注
Fail Whale
挑戰
一開始,我們的軟件是直接安裝在服務器,這意味著軟件可靠性依賴硬件,電源、網絡以及其他的環境因素都是威脅。這種情況下,如果要增加容錯能力,就需要統籌考慮這些互不關聯的物理設備因素及在上麵運行的服務。
最早采購數據中心方案的時候,我們都還是菜鳥,對於站點選擇、運營和設計都非常不專業。我們先直接托管主機,業務增長後我們改用租賃機房。早期遇到的問題主要是因為設備故障、數據中心設計問題、維護問題以及人為操作失誤。我們也在持續迭代我們的硬件設計,從而增強硬件和數據中心的容錯性。
服務中斷的原因有很多,其中硬件故障常發生在服務器、機架交換機、核心交換機這地方。舉一個我們曾經犯過的錯誤,硬件團隊最初在設計服務器的時候,認為雙路電源對減少供電問題的意義不大 -- 他們真的就移除了一塊電源。然而數據中心一般給機架提供兩路供電來提高冗餘性,防止電網故障傳導到服務器,而這需要兩塊電源。最終我們不得不在機架上增加了一個 ATS 單元(交流切換開關AC transfer switch)來接入第二路供電。
提高係統的可靠性靠的就是這樣的改進,給網絡、供電甚至機房增加冗餘,從而將影響控製到最小範圍。
我們學到的教訓以及技術的升級、遷移和選型
我們學到的第一個教訓就是要先建模,將可能出故障的地方(例如建築的供電和冷卻係統、硬件、光纖網絡等)和運行在上麵的服務之間的依賴關係弄清楚,這樣才能更好地分析,從而優化設計提升容錯能力。
我們增加了更多的數據中心提升地理容災能力,減少自然災害的影響。而且這種站點隔離也降低了軟件的風險,減少了例如軟件部署升級和係統故障的風險。這種多活的數據中心架構提供了代碼灰度發布staged code deployment的能力,減少代碼首次上線時候的影響。
我們設計新硬件使之能夠在更高溫度下正常運行,數據中心的能源效率因此有所提升。
下一步工作
隨著公司的戰略發展和運營增長,我們在不影響我們的最終用戶的前提下,持續不斷改進我們的數據中心。下一步工作主要是在當前能耗和硬件的基礎上,通過維護和優化來提升效率。
硬件的效率優化
曆史和挑戰
我們的硬件工程師團隊剛成立的時候隻能測試市麵上現有硬件,而現在我們能自己定製硬件以節省成本並提升效率。
Twitter 是一個很大的公司,它對硬件的要求對任何團隊來說都是一個不小的挑戰。為了滿足整個公司的需求,我們的首要工作是能檢測並保證購買的硬件的品質。團隊重點關注的是性能和可靠性這兩部分。對於硬件我們會做係統性的測試來保證其性能可預測,保證盡量不引入新的問題。
隨著我們一些關鍵組件的負荷越來越大(如 Mesos、Hadoop、Manhattan、MySQL 等),市麵上的產品已經無法滿足我們的需求。同時供應商提供的一些高級服務器功能,例如 Raid 管理或者電源熱切換等,可靠性提升很小,反而會拖累係統性能而且價格高昂,例如一些 Raid 控製器價格高達係統總報價的三分之一,還拖累了 SSD 的性能。
那時,我們也是 MySQL 數據庫的一個大型用戶。SAS(串行連接 SCSISerial Attached SCSI)設備的供應和性能都有很大的問題。我們大量使用 1U 規格的服務器,它的磁盤和回寫緩存一起也隻能支撐每秒 2000 次的順序 IO。為了獲得更好的效果,我們隻得不斷增加 CPU 核心數並加強磁盤能力。我們那時候找不到更節省成本的方案。
後來隨著我們對硬件需求越來越大,我們成立了一個硬件團隊,從而自己來設計更便宜更高效的硬件。
關鍵技術變更與選擇
我們不斷的優化硬件相關的技術,下麵是我們采用的新技術和自研平台的時間軸。
- 2012 - 采用 SSD 作為我們 MySQL 和 Key-Value 數據庫的主要存儲。
- 2013 - 我們開發了第一個定製版 Hadoop 工作站,它現在是我們主要的大容量存儲方案。
- 2013 - 我們定製的解決方案應用在 Mesos、TFE( Twitter Front-End )以及緩存設備上。
- 2014 - 我們定製的 SSD Key-Value 服務器完成開發。
- 2015 - 我們定製的數據庫解決方案完成開發。
- 2016 - 我們開發了一個 GPU 係統來做模煳推理和訓練機器學習。
學到的教訓
硬件團隊的工作本質是通過做取舍來優化 TCO(總體擁有成本),最終達到達到降低 CAPEX(資本支出)和 OPEX(運營支出)的目的。概括來說,服務器降成本就是:
- 刪除無用的功能和組件
- 提升利用率
Twitter 的設備總體來說有這四大類:存儲設備、計算設備、數據庫和 GPU 。 Twitter 對每一類都定義了詳細的需求,讓硬件工程師更針對性地設計產品,從而優化掉那些用不到或者極少用的冗餘部分。例如,我們的存儲設備就專門為 Hadoop 優化過,設備的購買和運營成本相比於 OEM 產品降低了 20% 。同時,這樣做減法還提高了設備的性能和可靠性。同樣的,對於計算設備,硬件工程師們也通過移除無用的特性獲得了效率提升。
一個服務器可以移除的組件總是有限的,我們很快就把能移除的都扔掉了。於是我們想出了其他辦法,例如在存儲設備裏,我們認為降低成本最好的辦法是用一個節點替換多個節點,並通過 Aurora/Mesos 來管理任務負載。這就是我們現在正在做的東西。
對於這個我們自己新設計的服務器,首先要通過一係列的標準測試,然後會再做一係列負載測試,我們的目標是一台新設備至少能替換兩台舊設備。最大的性能提升來自增加 CPU 的線程數,我們的測試結果表示新 CPU 的 單線程能力提高了 20~50% 。同時由於整個服務器的線程數增加,我們看到單線程能效提升了 25%。
這個新設備首次部署的時候,監控發現新設備隻能替換 1.5 台舊設備,這比我們的目標低了很多。對性能數據檢查後發現,我們之前對負載特性的一些假定是有問題的,而這正是我們在做性能測試需要發現的問題。
對此我們硬件團隊開發了一個模型,用來預測在不同的硬件配置下當前 Aurora 任務的填充效率。這個模型正確的預測了新舊硬件的性能比例。模型還指出了我們一開始沒有考慮到的存儲需求,並因此建議我們增加 CPU 核心數。另外,它還預測,如果我們修改內存的配置,那係統的性能還會有較大提高。
硬件配置的改變都需要花時間去操作,所以我們的硬件工程師們就首先找出幾個關鍵痛點。例如我們和 SRE(網站可靠性工程師Site Reliability Engineer)團隊一起調整任務順序來降低存儲需求,這種修改很簡單也很有效,新設備可以代替 1.85 個舊設備了。
為了更好的優化效率,我們對新硬件的配置做了修改,隻是擴大了內存和磁盤容量就將 CPU 利用率提高了20% ,而這隻增加了非常小的成本。同時我們的硬件工程師也和合作生產廠商一起為那些服務器的最初出貨調整了物料清單。後續的觀察發現我們的自己的新設備實際上可以代替 2.4 台舊設備,這個超出了預定的目標。
從裸設備遷移到 mesos 集群
直到 2012 年為止,軟件團隊在 Twitter 開通一個新服務還需要自己操心硬件:配置硬件的規格需求,研究機架尺寸,開發部署腳本以及處理硬件故障。同時,係統中沒有所謂的“服務發現”機製,當一個服務需要調用一個另一個服務時候,需要讀取一個 YAML 配置文件,這個配置文件中有目標服務對應的主機 IP 和端口信息(預留的端口信息是由一個公共 wiki 頁麵維護的)。隨著硬件的替換和更新,YAML 配置文件裏的內容也會不斷的編輯更新。在緩存層做修改意味著我們可以按小時或按天做很多次部署,每次添加少量主機並按階段部署。我們經常遇到在部署過程中 cache 不一致導致的問題,因為有的主機在使用舊的配置有的主機在用新的。有時候一台主機的異常(例如在部署過程中它臨時宕機了)會導致整個站點都無法正常工作。
在 2012/2013 年的時候,Twitter 開始嚐試兩個新事物:服務發現(來自 ZooKeeper 集群和 Finagle 核心模塊中的一個庫)和 Mesos(包括基於 Mesos 的一個自研的計劃任務框架 Aurora ,它現在也是 Apache 基金會的一個項目)。
服務發現功能意味著不需要再維護一個靜態 YAML 主機列表了。服務或者在啟動後主動注冊,或者自動被 mesos 接入到一個“服務集”(就是一個 ZooKeeper 中的 znode 列表,包含角色、環境和服務名信息)中。任何想要訪問這個服務的組件都隻需要監控這個路徑就可以實時獲取到一個正在工作的服務列表。
現在我們通過 Mesos/Aurora ,而不是使用腳本(我們曾經是 Capistrano 的重度用戶)來獲取一個主機列表、分發代碼並規劃重啟任務。現在軟件團隊如果想部署一個新服務,隻需要將軟件包上傳到一個叫 Packer 的工具上(它是一個基於 HDFS 的服務),再在 Aurora 配置上描述文件(需要多少 CPU ,多少內存,多少個實例,啟動的命令行代碼),然後 Aurora 就會自動完成整個部署過程。 Aurora 先找到可用的主機,從 Packer 下載代碼,注冊到“服務發現”,最後啟動這個服務。如果整個過程中遇到失敗(硬件故障、網絡中斷等等), Mesos/Aurora 會自動重選一個新主機並將服務部署上去。
Twitter 的私有 PaaS 雲平台
Mesos/Aurora 和服務發現這兩個功能給我們帶了革命性的變化。雖然在接下來幾年裏,我們碰到了無數 bug ,傷透了無數腦筋,學到了分布式係統裏的無數教訓,但是這套架還是非常讚的。以前大家一直忙於處理硬件搭配和管理,而現在,大家隻需要考慮如何優化業務以及需要多少係統能力就可以了。同時,我們也從根本上解決了 Twitter 之前經曆過的 CPU 利用率低的問題,以前服務直接安裝在服務器上,這種方式無法充分利用服務器資源,任務協調能力也很差。現在 Mesos 允許我們把多個服務打包成一個服務包,增加一個新服務隻需要修改配額,再改一行配置就可以了。
在兩年時間裏,多數“無狀態”服務遷移到了 Mesos 平台。一些大型且重要的服務(包括我們的用戶服務和廣告服務係統)是最先遷移上去的。因為它們的體量巨大,所以它們從這些服務裏獲得的好處也最多,這也降低了它們的服務壓力。
原文發布時間為:2016-10-08
本文來自雲棲社區合作夥伴“Linux中國”
最後更新:2017-06-06 16:02:28