從 B 站崩潰報告看分布式系統的技術棧
?不知道大家還記得去年 B 站(嗶哩嗶哩)掛了那次嚴重的事故不,記得當時在全網也是引起了熱議。
離當時過去剛好一年多的時間,今天看到 B 站前兩天在公眾號上發的復盤報告。2021.07.13 我們是這樣崩的 文章從八個方面全鏈路再現了當時事故發生和處理的全過程:
包括至暗時刻,初因定位,故障止損,根因定位,原因說明,問題分析,優化改進,總結。
不知道大家看過沒,我全文看了一下,看完還挺唏噓的,最終原因竟然是一個字符串類型的數字參數 0 導致的死循環。
不過文章本身寫的還是非常專業和嚴謹,對于咱們技術的同學,好嘛,也是一次難得的學習機會。
只是,看到文章最后一段代碼,我實在忍不住多說幾句,一個求最大公約數的GCD 函數,居然就是導致 B 站崩潰的元兇..
因為,下面這段代碼對我來說實在太熟悉不過了,在學校搞過程序競賽的同學應該對它都不陌生吧。
看到上面的報告,第一感覺是因為沒有做好類型轉換帶來的死循環,是個弱類型設計的坑,如果除零是拋出異常而不是變 NaN,應該很快就能定位到問題所在。
另外,從官方的這份報告里,我看到了多次提及多活,容災,分布式這個詞匯,異地多活是常見的分布式系統保證架構穩定性的一個方案。
畢竟這么體量的公司,系統架構肯定和分布式是繞不開的。那咱們以此來看看,分布式系統里面都有哪些技術棧呢?
之前記得在左耳朵耗子叔的專欄《左耳聽風》里專門有寫分布式架構,我把里面的部分內部摘抄在這里給大家分享。
構建分布式系統的目的是增加系統容量,提高系統的可用性,轉換成技術方面,也就是完成下面兩件事。
- 大流量處理。通過集群技術把大規模并發請求的負載分散到不同的機器上。
- 關鍵業務保護。提高后臺服務的可用性。
說白了就是干兩件事。一是提高整體架構的吞吐量,服務更多的并發和流量,二是為了提高系統的穩定性,讓系統的可用性更高。
提高架構的性能
咱們先來看看,提高系統性能的常用技術。
緩存系統。加入緩存系統,可以有效地提高系統的訪問能力。比如從前端的瀏覽器,到網絡,再到后端的服務,底層的數據庫、文件系統、硬盤和 CPU,全都有緩存,這是提高快速訪問能力最有效的手段。對于分布式系統下的緩存系統,需要的是一個緩存集群。比如用一個 Proxy 來做緩存的分片和路由。
負載均衡系統。負載均衡系統是水平擴展的關鍵技術,它可以使用多臺機器來共同分擔一部分流量請求。
異步調用。異步系統主要通過消息隊列來對請求做排隊處理,這樣可以把前端的請求的峰值給“削平”了,所謂削峰填谷。而后端通過自己能夠處理的速度來處理請求。這樣可以增加系統的吞吐量,但是實時性就會有影響。同時,還會引入消息丟失的問題,所以要對消息做持久化,這會造成“有狀態”的結點,從而增加了服務調度的難度。
數據分區和數據鏡像。數據分區是把數據按一定的方式分成多個區(比如通過地理位置),不同的數據區來分擔不同區的流量。這需要一個數據路由的中間件,而數據鏡像是把一個數據庫鏡像成多份一樣的數據,這樣就不需要數據路由的中間件了??梢栽谌我饨Y點上進行讀寫,內部會自行同步數據。然而,數據鏡像中最大的問題就是數據的一致性問題。
提高架構的穩定性
接下來,咱們再來看看提高系統系統穩定性的一些常用技術。
服務拆分。服務拆分主要有兩個目的:一是為了隔離故障,二是為了重用服務模塊。但服務拆分完之后,會引入服務調用間的依賴問題。
服務冗余。 服務冗余是為了去除單點故障,并可以支持服務的彈性伸縮,以及故障遷移。然而,對于一些有狀態的服務來說,冗余這些有狀態的服務帶來了更高的復雜性。其中一個是彈性伸縮時,需要考慮數據的復制或是重新分片,遷移的時候還要遷移數據到其它機器上。
限流降級。當系統實在扛不住壓力時,只能通過限流或者功能降級的方式來停掉一部分服務,或是拒絕一部分用戶,以確保整個架構不會掛掉。這些技術屬于保護措施。
高可用架構。通常來說高可用架構是從冗余架構的角度來保障可用性。比如,多租戶隔離,災備多活,或是數據可以在其中復制保持一致性的集群??傊?,就是為了不出單點故障。
高可用運維。高可用運維指的是 DevOps 中的 CI/CD(持續集成 / 持續部署)。一個良好的運維應該是一條很流暢的軟件發布管線,其中做了足夠的自動化測試,還可以做相應的灰度發布,以及對線上系統的自動化控制。這樣,可以做到“計劃內”或是“非計劃內”的宕機事件的時長最短。上述這些技術非常有技術含量,而且需要投入大量的時間和精力。
正如不想當將軍的士兵不是好士兵,不想當架構師的程序員不是一個好的程序員,哈哈,道阻且長,慢慢加油吧。?