騰訊資深運維專家周小軍:QQ與微信架構的驚天祕密

yunweipai發表於2015-06-26

  社交領域一直是網際網路創業的大熱門,從PC到移動端,從OICQ、MSN到QQ。到了移動網際網路時代,社交領域應用開始徹底爆發,直奔黃金期。騰訊在過去幾年裡,社交平臺更是火到爆,QQ和微信坐擁幾億的粉絲,QQ空間和朋友圈各種刷屏,寫心得,曬照片,秀視訊,那麼誰來為企鵝保駕護航呢?支撐QQ和微信海量資料背後的架構又有哪些驚天內幕呢?本期大講堂的內容來自今年2月份ChinaUnix對騰訊社交網路運營服務中心資深資料運維專家周小軍的專訪。本期訪談將從運維的視角,為我們揭曉騰訊社交產品前端到後端的故事。

  Q1: 您好,很高興有機會採訪到您,我瞭解到您,您在天涯騰訊擁有非常豐富的運維工作經驗了,能否介紹下自己?分享下自己工作中的苦與樂?

  A1: 我叫周小軍,目前就職於騰訊社交網路平臺技術運營中心,負責社交產品分散式儲存的運維及團隊管理工作。

  我在運維領域工作了十多年,算是一個運維老兵。剛畢業時我進入國壽當系統管理員,負責系統和業務運維,也做過業務系統開發。較早接觸了SCO Unix作業系統和Informix資料庫,還做了一些業務系統開發。後來感覺在國企沒有技術,沒技術挑戰,技術部門也不是國企的核心,於是工作一段時間後離開了國壽。

  到了2002年,我進入天涯社群,主要負責網站運維。在天涯的職業生涯中,我從運維主管做到了雲端計算副總監,在此期間組建起了一支精銳的運維隊伍,包括系統、網路、資料庫、安全和運維開發等運維小團隊。

  隨著越來越多的網友湧向天涯社群,天涯流量開始突飛猛進了,我不斷推進網站的架構演進,從初始的二層架構發展到包括GSLB、LVS、Haproxy、Squid、應用WEB、資料快取及資料庫等多層可擴充套件的架構,從ASP/MSSQL/Windows平臺遷移到JSP/MySQL/Linux開源平臺,從指令碼化運維進化到了工具化運維,我們建設了一套包括資源管理、監控、告警、配置管理、自動部署等服務在內的運維管理系統,探索了虛擬化技術的實踐,保證了天涯從最初的日百萬PV演進到日億級PV架構。

  有句話說得好,叫摸著石頭過河。在天涯十多年的運維工作中,我們也踩到了許多大坑:比如被幾倍出口的DDOS打了幾小時、伺服器被入侵、域名被劫持、資料中心斷電、天涯拖庫、谷歌出走等大事件,還有許多員工犯下的人為致命錯誤。回過頭來看,當初踩坑多了,心理反倒變得極其強大,遇到大故障已如鋼絲一般冷靜,在反思總結教訓的基礎上不斷提升自己的運維能力。

  回顧我在天涯的時光裡,遇到技術上最大的困難是雙平臺並執行的問題,天涯從Windows遷移到Linux過程中,由於架構複雜、產品繁多、技術資源投入不足,整個遷移過程持續了數年。在這個過程中,運維團隊不得不在雙平臺上投入大量精力,比如開發運維工具要在Linux寫一套Python,在Windows上寫一套C#,運維精力很難兼顧。現在反思,有幾點經驗,希望做運維的夥伴們能夠共勉,做系統重構時必須要有堅定的目標,強有力的一把手決策,投入精兵強將小分隊,正確的說服老闆,敢於血戰,經受短時間的劇烈陣痛。

  2012年我進入騰訊負責社交產品分散式儲存運維,這裡是亞洲最大的分散式儲存叢集,上萬臺記憶體和磁碟儲存伺服器分佈在全國幾個區域的儲存倉庫內。每秒有幾千萬的資料讀寫請求,服務於QQ、空間、騰訊雲、相簿和廣點通等海量業務。

  與此同時,騰訊業務的海量資料給我們運維人員帶來了很大的挑戰,這些挑戰都是我們未曾經歷過的。我們不斷採用創新性的方法來解決這些難題,在儲存運維上開闢新的思路,不斷從效率、成本、質量和安全四個維度力求做得更專更精,不斷追求更卓越,非常給力地支援了業務的高速發展。

  Q2: 騰訊在過去的幾年裡,社交平臺火到爆,QQ和微信都已經擁有了幾億的粉絲,那麼如何應對QQ空間海量使用者上傳圖片、上傳視訊、上傳文字等高併發負載?

  A2: 針對文字、圖片和視訊的不同應用場景,我們提供了不同的儲存解決方案。其中有面向資料的NoSQL分散式儲存和關聯式資料庫,也有面向圖片的圖片儲存平臺,還有面向視訊的檔案儲存平臺。

  不同的儲存系統各有特點,NoSQL儲存注重高效能、低延遲和高可用,圖片和檔案儲存量更注重低成本和資料安全。

  騰訊NoSQL儲存由騰訊內部研發團隊開發,現在有基於記憶體和SSD二級儲存的CKV(Cloud Key-Value)、Grocery和Quorum_KV,有基於SSD儲存介質的TSSD等。

  CKV主要服務於空間、相簿、騰訊雲等網際網路業務,Grocery主要服務於QQ即通業務,Quorum_KV主要服務於微信訊息業務。

  經過精心設計的儲存單機效能可以達到每秒十幾萬次的讀寫,完全可以應對高併發負載。比如CKV的記憶體儲存採取了以下的設計思想以支援高併發能力:

  1)核心態網路處理模組,以核心模組形式提供服務;

  2)大量運用zero-copy思想,在資料傳遞,編解碼時基本達到理論上的最少次數;

  3)快速hash;

  4)記憶體快速分配;

  5)多佇列網路卡;

  6)處理器繫結;

  7)自旋鎖;

  8)儲存主機無磁碟IO的設計,備機才落流水和記憶體映象到磁碟。

  Q3: 八年前,騰訊就開始在社交產品中應用到了NoSQL資料庫了,大家可以通過微信朋友圈或者QQ空間輕鬆自由地分享視訊、文字、音訊、圖片等,那麼微信與QQ在架構上究竟有哪些相似點與不同點呢?

  A3: 微信使用的NoSQL儲存名稱為Quorum_KV,是基於LSMTree研發的強一致性、持久化KV分散式儲存,支援key-table 和 string-value兩種儲存模型。

  Quorum_KV通過Quorum協議實現雙向可寫功能,一個最小的儲存單元由二臺儲存機和一臺仲裁機組成,寫儲存機時經過仲裁決定被寫的機器。

  寫資料時直接寫記憶體的Memtable表。Memtable寫滿後轉換成Immutable。Immutable定期Dump到本地磁碟變成資料檔案,資料檔案不斷遞增形成不同level級別資料檔案,不同level級別的資料檔案會定期合併。

  記憶體表使用Skiplist來做記憶體的Key索引。

  讀資料時先讀記憶體表,如果找不到記錄再尋找Immutable,然後是level 0磁碟檔案、level 1……直至尋找到記錄返回結果。所以可以看到,Quorum_KV的設計是面向寫量大,讀量小的業務場景,很好地適應了微信訊息寫量大的特點。

  再來談談QQ,它使用的NoSQL儲存名稱為Grocery,屬於最終一致性,持久化KV分散式儲存,支援Key-value和Key-key-Row資料結構。

  一個最小的儲存單元由二臺或多臺儲存主、備組成,主備可組成一主多備的鏈狀結構。資料寫入主後同步到備。客戶端可同時讀取主備,因此讀到備的客戶端會有一定的資料延遲,適合對資料一致性要求不高的業務。

  資料的讀寫都在記憶體中進行,記憶體的Key採用多階HASH來索引,讀寫效能極高,但受資料容量受記憶體的限制。資料在主、備上都落盤,保證了資料的永續性。一個儲存叢集可以支援業務混合儲存,業務Key採用一致性HASH方式分佈。可以看到,和Quorum_KV不同,Grocery的設計是面向寫量、讀量均大的業務。

  Q4: 從儲存的“五分鐘原則”可知,當資料五分鐘內被訪問一次,該資料不應儲存在硬碟,而應該儲存在記憶體中,對坐擁幾億使用者的QQ和微信等社交產品,可能要應對每秒幾千萬的讀寫請求,能否和我們分享下背後的叢集是如何支撐起這種大規模的分散式儲存?

  A4: QQ線上峰值高達二億多,每秒要響應幾千萬的讀寫請求,對分散式儲存的壓力非常大。傳統的關係型資料庫在高效能、分散式方面存在一些瓶頸,很難適應QQ海量業務場景所帶來的挑戰。

  如我之前說提及的,騰訊的NoSQL儲存系統經過精心設計,已經能夠應對海量資料的高併發、高可用、低延遲的應用場景,由幾百臺儲存機組成的儲存叢集可以輕鬆扛起數百萬的讀寫併發。叢集的效能具有線性擴充套件,叢集最大可以容納到幾千臺儲存伺服器。當然如此龐大的叢集,相應地也會帶來管理上的複雜,因此我們的一個叢集不會超過1千臺伺服器。

  在叢集中,記錄通過一致性HASH、號段範圍或HASH取模等方式,均勻分佈到後端的數百臺儲存裝置。儲存前端採用儲存代理,遮蔽了應用對儲存的直接訪問,資料在叢集擴充套件或收縮的過程中,通過代理的自動定址保證了業務無對儲存的無損訪問。業務資料從1臺儲存擴充套件到100臺儲存,只需要數分鐘即可完成,在此過程,業務是無感知的。

  此外,應對儲存叢集的運維,我們還有強大的儲存排程平臺,可以保證叢集中的代理和儲存做到平均水位,避免有的機器忙死,不斷應對高負載的壓力、而有的機器應對低負載,出現閒置等問題。

  最後,針對儲存的記憶體問題,我想補充一點,業務的資料具有冷熱區域,儲存系統把熱資料儲存在記憶體中,冷資料儲存在SSD盤中。淘汰系統通過KEY的過期時間自動把冷資料從記憶體淘汰到SSD盤,以釋放記憶體空間。當冷資料第一次從SSD盤讀取後會自動上升到記憶體。

  Q5: 在國內網路環境下,單機房的可靠性無法滿足大型網際網路服務的要求,如機房掉電,光纜被挖的情況也發生過,微信和QQ有沒有出現過伺服器當機的時候?您們當時是如何應急處理的?有沒有更好的容災機制來確保高可用性?

  A5: 早期的QQ在單IDC時代,的確有過光纜被挖斷、甚至城市運營商出口故障導致服務中斷數小時的大故障。現在騰訊已經建設起成熟的海量服務運營體系,面對單機房的可靠性採用了全網排程理念來解決跨地域之上的高可用性。

  首先是SET標準化。SET是標準業務部署模組,接入層、邏輯層和儲存層標準化成不同的SET。

  每個SET內都有固定數量的伺服器和標準服務容量。譬如,上海XX接入SET設計容量XXX萬使用者,當前使用者數為XXX萬,離警戒水位還有XX%,XX小時後可進入擴容點。

  SET都具有自動化部署能力,幾百臺伺服器的SET部署時間小於10分鐘。SET按單元分佈在不同城市之間。每個重點城市都會部署許多套接入SET,邏輯SET和儲存SET。

  第三,SET間、城市間、區域間都具備全網排程能力。使用者到接入SET的排程通過GLBS來切換,譬如接入SET會有許多個VIP,通過域名服務變更VIP就可以把使用者請求從天津切到上海。

  接入SET到邏輯SET,或邏輯SET到儲存SET的訪問則通過內部名字服務系統來切換。這樣當任何一個IDC或某城市出現問題時,運維人員通過排程可以在幾分鐘內把流量切到正常的SET,甚至可以通過排程系統做到自動化切換。

  第四,儲存層的多地同步。儲存層會在三地以上部署多套,譬如華南、華中和華北各部署一套儲存SET。有寫請求時先寫華南SET,寫成功後通過同步中心把資料同步到華中和華北SET,通過最終一致性保證資料儲存在多地儲存。資料在三地同步最長時間才幾千毫秒,因此使用者對資料的不一致基本無感知。

  最後是系統的柔性策略。柔性可用即對服務進行分級,當系統變得不可靠的時候,優先提供重要優先順序的服務。比如節假日使用者大量訪問相簿出現流量峰值時,突然出現某機房核心專線故障,柔性系統會把相簿從全尺寸圖片瀏覽模式切到縮圖瀏覽模式,以減少圖片的拉取,降低頻寬流量,減少壓力。

  Q6: 在朋友圈的相簿、QQ空間的相簿裡,或多或少會有一些個人隱私的資料,一旦丟失,後果很嚴重,那麼它們對應的伺服器叢集是如何來確保資料的備份與安全性?

  A6: 分散式儲存系統都具有主備雙機或主備多機架構。備機把更新流水落本地硬碟,並定期把記憶體映象到磁碟。後端有統一的冷備系統來儲存備份資料。因此資料的安全性是非常強的。

  關鍵業務還有三地以上的儲存SET同步,實現跨城容災。

  圖片儲存在分散式圖片儲存系統中,同樣也會儲存三份以上的副本,並且有跨地域的容災副本。

  Q7: 您在網際網路行業積累了十多年的運維經驗了,對很多朋友來講,要想成為一名優秀的DevOps工程師,在成長道路上,您有哪些心得經驗分享?

  A7: 在運維道路上,我的切身體會比較多,簡單總結一下主要有以下幾點:

  1、堅定的目標

  目標是職業生涯遠處的燈塔,它能衝破迷霧,讓你在迷惘中堅定信念和方向。要想成為一名優秀的技術專家就要牢牢樹立你的目標,持之以恆,每天一點一滴地前進。

  2、運維服務能力

  餐飲業的海底撈以服務口碑得到顧客的認可。同樣,運維人員做為支撐服務部門,也要通過服務來獲得使用者和業務的認同。我們要以超出使用者預期的目標來為使用者和業務提供服務。

  可能有人要問,我們是技術人員,為什麼要特別強調服務能力?我覺得技術運維的團隊目標不是提供功能的業務,而應該是提供持續化的服務能力,如資源交付能力,變更能力,可用效能力,排程能力等等,讓業務如同水和電一樣使用我們的服務。在這些服務能力的背後需要長時間的建設和積累。

  例如傳統的DBA團隊重在技術支援,而我們資料運維團隊除了技術支援之外,提供專業的服務已經成為團隊的核心目標。

  在服務能力上要致力於做到超出使用者預期。什麼是超出使用者預期?就是使用者期望得到五星的服務,而你能給他們提供到六星的服務。

  要獲得超出預期的服務,我認為要做好以下二方面:

  1)主動服務

  在我們運營中心,有句口話為“服務使用者、服務業務、服務自己”,也就是說在做事時要考慮,我們的服務目標是誰。我們在制定目標和方向的時候不能只考慮到自己,要把眼光放得更長,看到業務,看到使用者。

  這裡有一個例子,業務在申請裝置資源時,按部就班走硬體成本資源採購是B級服務;通過虛擬化技術把裝置申請從周提升到小時是A級服務;在虛擬化技術之上通過排程能力保證業務上線後,能根據實際流量實現人工或自動化的資源伸縮,即節省了成本,提高業務部署速度,還提升了運維能力,這就是S級超出預期的服務。

  2)提供超出預期的服務,還要主動站在使用者角度替使用者思考,給使用者帶來價值,實現多方共贏。

  譬如我們在設計程式碼釋出系統時應該要思考,釋出系統的初步目標是減少了運維團隊的工作量,同時也提升了應用團隊的釋出效率。但通過更深入的思考我們還會發現,如果具備灰度釋出能力,我們可以做到對使用者無損。釋出過程中引入自動化測試,我們可以保證了應用的可用性。通過多佇列服務和生產者/消費者模式,我們可以瞬間完成數千臺伺服器的釋出,等等。做這些事情時,站在多方面來思考會讓運維工作變得有價值,而不是背黑鍋的角色。

  3、一萬小時的專業技術積累和豐富的實戰

  丹尼爾在《一萬小時天才理論》提出一萬小時定律,即要成為某個領域的專家,需要積累一萬小時,如果每天工作中花在學習和實踐上的時間達到4小時,那麼成為一個領域的專家至少需要十年。

  因此我們在工作中要善於利用時間,儘量保證20%的工作時間用在提升專業能力和運維效率方面。即使是加班時間也要把時間用在提升效率的工作上,避免加班仍是做重複性而無技術含量的事情。

  “紙上得來終覺淺,絕知此事要躬行”。要把技術運用得弓馬嫻熟,武藝精通,就得把知識落地,應用到實踐中,在工作中不斷提出新想法,勇於嘗試新事物,不斷給自己新的挑戰。

  4、不斷打破心理舒適期尋求突破

  工作到一定程度後就會進入心理舒適期,這是讓人感到熟悉、駕輕就熟時的心理狀態。這個時候就要勇於打破心理舒適期,從這個方面去突破自己的天花板。

  打破心理舒適期就要保持自我動因,譬如對技術的熱愛,保持強烈的好奇心,給自己設立中長期目標,對工作和事業的自我驅動力等。

  在突破的領域上,運維人員不僅只是侷限於運維技術層面,在溝通表達、專案管理、業務、產品、開發等方面都要獲得成長。

  打破舒適期甚至要勇於跳離舒適的崗位、穩定的公司,尋求更好的職業發展平臺,這樣才把保證自己的價值不斷獲得增值,打破“IT只是吃青春飯”的悲觀宿論。

  5、開發能力

  運維自動化有三個階段,指令碼化是第一階段,工具化是第二個階段,產品化是第三個階段。運維人員要掌握開發能力,來提升運維效率,解放運維生產力。

  運維的開發語言可選Python、PHP甚至C/C++等。有些優秀的運維人員可能是全棧工程師,從前端到後端,從WEB開發到後臺開發都可以自己解決。

  除了開發能力,運維人員還要深入瞭解運維需求和業務需求,規劃設計具有前瞻性的運維產品,用產品的理念來做運維繫統。優秀的運維繫統需要具備出色的使用者體驗,並通過模組化、鬆耦合的設計,方便其他工程師在平臺上的二次開發,以提升運維開發效率和運維效率。

  好的運維產品可以開源出來,回饋業界,為外界弱小的運維團隊提供更大的幫助以及貢獻度。

  精通開發還便於理解業務,和開發一起共同推動業務架構的優化,成為開發的緊密合作夥伴。

  具備開發能力還可以讓運維工程師掌握進入系統內部的鑰匙。運維工程師通過閱讀Linux核心原始碼、MySQL原始碼或者Redis原始碼等,能更深入掌握作業系統、資料庫和網路框架等服務的執行機制,根據業務特點改寫功能特性,使之更能符合業務需求。好的特性還能回饋提交社群,以結合到下一個版本中。

相關文章