就鹿晗宣佈戀情導致微博當機事件淺談大型網站高可用性架構

EakonZhao發表於2017-10-08

中午吃飯刷著刷著微博發現微博突然掛了。我一開始以為是家裡網不好,後來換了流量刷還是刷不出內容,並且報error,我就知道微博應該是掛了。往朋友圈一看,原來是鹿晗和關曉彤微博互圈“宣佈戀情”了。要不是以前看過《好先生》這部劇沒準我還真不認識關曉彤。陸地cp前幾天不是還在炒著嗎?怎麼這麼突然?誒..貴圈賊亂啊。

作為一名程式設計師,我更感興趣的是微博如何應對瞬時湧來的高併發大流量。從很久很久以前文章馬伊琍的“週一見”,到後來“出軌隊”、“吸毒隊”的爭相奪分,再到前段時間的郭敬明事件、薛之謙事件,再到今天的鹿晗宣佈戀情......微博看似每次都在掛,一直都沒有進步,大家每次遇到熱點事件刷不出內容的時候都會吐槽微博的應用平臺很辣雞。但是呢,微博的後臺系統肯定一直在重構升級優化,我覺得能夠做到今天這種水平已經很不錯了。

從使用者的角度(主要是我的角度hhhhh)來看

遇到熱點事件的時候微博大概率在短時間內(大約10~15)可能會完全刷不出內容,過了一段時間之後(大約半小時)進行間隔重新整理(間隔10秒左右),有可能某些時候會看到5xx的error,5開頭的http狀態碼代表伺服器或者是閘道器存在問題,比如說伺服器拒絕連線、閘道器超時或者是應用程式碼存在bug等都會導致5xx的錯誤。在熱點事件發生1小時內,系統應該可以恢復正常的服務。

從網站開發、運維人員的角度來看

  • 運維:臥槽?怎麼訪問流量這麼高?是出啥bug了嗎?臥槽!不會是又有人出軌吸毒了吧?emmmm....我的國慶假期可還沒結束啊!
  • 運維:兄弟們,快醒醒!快加機器啊!系統要崩了!
  • 開發:別催!再催自殺!
  • leader:測試在擴容之後趕緊拉出來測測!
  • 測試:人在家中躺,鍋從天上來!

上面都是我亂說的!

為什麼我覺得微博在高併發大流量訪問方面的表現已經很不錯了呢?舉個例子吧:淘寶每年在雙11購物節的時候也要應對高併發的場景,但是這是可以提前做很多準備的,比如說提前購買頻寬資源、增加伺服器資源、進行完備的異地容災等等,很多都是可預測的。而微博呢?熱點事件隨時都可能發生,所以這對於微博的運維工程師來說是很大的考驗。當然,現在的運維平臺也是非常的智慧了,可以對各項指標進行實時監控,一有異常,馬上進行簡訊或者郵件報警,之後就是各個崗位的工程師人肉上場調配各類資源了。

那微博在平時為什麼不增加一些伺服器資源呢?

伺服器資源、網路頻寬資源等既重要,又昂貴。由於並不是每時每刻都必須應對高併發的場景,因此如果說在平時增加了冗餘的伺服器資源導致大量機器空載,也是一種很大的浪費。我們在考慮提供可用服務的同時,也必須考慮一下成本。

本來我開始寫這篇部落格的時候就是想回顧一下自己以前學習過的大型網站高可用架構相關知識。但是由於高效能、伸縮性、擴充性與高可用性密不可分,所以我寫著寫著就感覺寫不下去了。想寫的東西太多了,有點不知道從哪裡開始寫。所以下面我就針對高可用性架構中經常會提到的幾個點來講講。

大型網站高可用架構

不管是對於小型網站還是大型網站來說,分層都是必須的:粗粒度的分層一般為應用層、業務層和資料層。橫向分層之後,可能還會根據模組的不同對每一層進行縱向的分割。拿微博舉例,我覺得它的評論模組和點贊模組應該是解耦的。越是複雜的系統,橫向和縱向的分層分割粒度就會越細。很多時候你用起來以為它就是一個系統,其實後面可能是由幾百上千個獨立部署的系統對外提供服務。

叢集

叢集在大型網站架構中是一個非常非常重要的概念。由於伺服器(不管是應用伺服器還是資料伺服器)容易發生單點問題,一旦一臺伺服器gg了,就必須進行失效轉移。

應用伺服器叢集

一般來說,應用伺服器必須是無狀態的。什麼叫無狀態伺服器呢?在介紹它之前,我們先來說一下狀態伺服器:狀態伺服器一般會儲存請求相關的資訊,每個請求會預設地使用以前的請求資訊。這樣就很容易導致會話粘滯問題:如果一臺狀態伺服器當機了,那麼它儲存的請求資訊(例如session)就丟失了,可能會導致不可預知的問題。
那麼相對的,無狀態伺服器就不儲存請求資訊,它處理的客戶資訊必須由請求自己攜帶,或者是從其他伺服器叢集獲取。因此無狀態伺服器相對於狀態伺服器來說更加地健壯,就算是重啟伺服器甚至是伺服器當機都不會丟失狀態。由此引申出來的另一個優點就是方便擴容:只要在增加的伺服器上部署相同的應用並做好反向代理就能對外提供正常的服務。

session管理

既然應用伺服器是無狀態的,那麼使用者的登入資訊(session)如何管理呢?比較常見的有下面四種方式。但是由於前三種都有很大的侷限性,這裡只聊聊基於叢集的session伺服器管理方式。

  • session複製
  • 源地址hash(session繫結)
  • 用cookie記錄session
  • session伺服器

    我們在這裡是將伺服器的狀態進行分離:分為無狀態的應用伺服器和有狀態的session伺服器。當然,這裡說的session伺服器肯定說的是session伺服器叢集。我們可以藉助分散式快取或者是關係型資料庫來儲存session。對於微博來說,這裡肯定得用分散式快取了:因為用關係型資料庫的話資料庫連線資源容易成為瓶頸,並且I/O操作也很耗時間。比較常見的K-V記憶體資料庫有Redis。我覺得微博內容中的贊數、使用者的關注數和粉絲數用Redis來存應該算是比較合適的。

負載均衡

既然提到了叢集,肯定得說說負載均衡。但是感覺負載均衡應該可以歸類到可伸縮性裡面去,所以這裡就不詳細講啦,就簡單說說有哪些常見的負載均衡的方式以及負載均衡演算法。

負載均衡方式
  • HTTP重定向負載均衡
  • DNS域名解析負載均衡
  • 反向代理負載均衡
  • IP負載均衡
  • 資料鏈路層負載均衡
負載均衡演算法
  • 輪詢法
  • 隨機法
  • 源地址雜湊
  • 加權輪詢
  • 加權隨機
  • 最小連線數

插播點別的

突然想到一個比較有意思的東西:在微博的架構中,應該採用的是非同步拉模型而不是同步推模型。什麼意思呢?我們舉個例子:鹿晗的粉絲有3000多萬,關曉彤的粉絲有1000多萬。假如他倆發了條微博的同時需要往這4000萬粉絲的內容列表中(假設這裡用的是關係型資料庫)推送過去,這就是簡化的同步推模型。

那這樣有什麼缺點呢?首先,這樣會消耗大量的資料庫連線資源,更重要的是這樣不太符合軟體設計規範:因為對於兩人的粉絲來說,分別由有3000多萬和1000多萬的資料是冗餘的。假如說陳赫、鄧超在第一時間對他倆的微博進行了點贊,此時瓶頸就來了:剛才往資料庫裡插入4000多萬感覺還可以接受,但是現在四人的粉絲數加起來好幾億了,同時往資料庫插這麼多資料是不是感覺不太合適?

沒關係,我們現在換一種內容推送方式:我們現在不用同步推了,而是用非同步拉。我們每次在手機上刷微博的時候,如果想要看到更新的內容是不是都要下拉重新整理獲取?沒錯這就是非同步拉。非同步拉有什麼好處呢?很明顯的一個好處就是可以將熱點資料進行集中管理,並且不用進行大量的資料插入冗餘操作。另外對系統資源的消耗也較少。那麼微博內容從哪裡拉呢?主流的解決方案是把熱點內容放到快取中,每次都去查快取,這樣可以減少I/O操作並且避免發生因資源枯竭造成的超時問題。

PS:寫到這裡的時候我開始水群了,現在回過頭來繼續寫感覺沒法兒寫下去了。太久沒寫部落格了,很多知識略有遺忘。不過今天算是在腦海中把相關的東西梳理了一下,因為畢業設計也打算做高併發大流量相關的東西。今天算是蹭蹭熱點順便複習一下以前學過的知識吧~

其實高可用性架構還包括服務升級、服務降級、資料備份、失效轉移等等。關於網站高可用、高效能、高擴充方面感覺其實還有很多很多東西來寫。但是有些知識沒有一定的實踐經驗呢,又不能很好的掌握。那麼就等我後面再慢慢聊吧~

最後,打個廣告:之前一直在簡書上寫技術部落格,但是慢慢地感覺簡書雜七雜八的內容太多了,一點也不純粹。打算以後休閒娛樂的東西就放到簡書上寫吧,技術部落格慢慢會轉移到掘金的陣地上來了。關注簡書作者-EakonZhao

相關文章