從 B 站崩潰報告看分布式系統(tǒng)的技術(shù)棧
?不知道大家還記得去年 B 站(嗶哩嗶哩)掛了那次嚴重的事故不,記得當(dāng)時在全網(wǎng)也是引起了熱議。
離當(dāng)時過去剛好一年多的時間,今天看到 B 站前兩天在公眾號上發(fā)的復(fù)盤報告。2021.07.13 我們是這樣崩的 文章從八個方面全鏈路再現(xiàn)了當(dāng)時事故發(fā)生和處理的全過程:
包括至暗時刻,初因定位,故障止損,根因定位,原因說明,問題分析,優(yōu)化改進,總結(jié)。
不知道大家看過沒,我全文看了一下,看完還挺唏噓的,最終原因竟然是一個字符串類型的數(shù)字參數(shù) 0 導(dǎo)致的死循環(huán)。
不過文章本身寫的還是非常專業(yè)和嚴謹,對于咱們技術(shù)的同學(xué),好嘛,也是一次難得的學(xué)習(xí)機會。
只是,看到文章最后一段代碼,我實在忍不住多說幾句,一個求最大公約數(shù)的GCD 函數(shù),居然就是導(dǎo)致 B 站崩潰的元兇..
因為,下面這段代碼對我來說實在太熟悉不過了,在學(xué)校搞過程序競賽的同學(xué)應(yīng)該對它都不陌生吧。

看到上面的報告,第一感覺是因為沒有做好類型轉(zhuǎn)換帶來的死循環(huán),是個弱類型設(shè)計的坑,如果除零是拋出異常而不是變 NaN,應(yīng)該很快就能定位到問題所在。
另外,從官方的這份報告里,我看到了多次提及多活,容災(zāi),分布式這個詞匯,異地多活是常見的分布式系統(tǒng)保證架構(gòu)穩(wěn)定性的一個方案。
畢竟這么體量的公司,系統(tǒng)架構(gòu)肯定和分布式是繞不開的。那咱們以此來看看,分布式系統(tǒng)里面都有哪些技術(shù)棧呢?
之前記得在左耳朵耗子叔的專欄《左耳聽風(fēng)》里專門有寫分布式架構(gòu),我把里面的部分內(nèi)部摘抄在這里給大家分享。
構(gòu)建分布式系統(tǒng)的目的是增加系統(tǒng)容量,提高系統(tǒng)的可用性,轉(zhuǎn)換成技術(shù)方面,也就是完成下面兩件事。
- 大流量處理。通過集群技術(shù)把大規(guī)模并發(fā)請求的負載分散到不同的機器上。
- 關(guān)鍵業(yè)務(wù)保護。提高后臺服務(wù)的可用性。
說白了就是干兩件事。一是提高整體架構(gòu)的吞吐量,服務(wù)更多的并發(fā)和流量,二是為了提高系統(tǒng)的穩(wěn)定性,讓系統(tǒng)的可用性更高。
提高架構(gòu)的性能
咱們先來看看,提高系統(tǒng)性能的常用技術(shù)。

緩存系統(tǒng)。加入緩存系統(tǒng),可以有效地提高系統(tǒng)的訪問能力。比如從前端的瀏覽器,到網(wǎng)絡(luò),再到后端的服務(wù),底層的數(shù)據(jù)庫、文件系統(tǒng)、硬盤和 CPU,全都有緩存,這是提高快速訪問能力最有效的手段。對于分布式系統(tǒng)下的緩存系統(tǒng),需要的是一個緩存集群。比如用一個 Proxy 來做緩存的分片和路由。
負載均衡系統(tǒng)。負載均衡系統(tǒng)是水平擴展的關(guān)鍵技術(shù),它可以使用多臺機器來共同分擔(dān)一部分流量請求。
異步調(diào)用。異步系統(tǒng)主要通過消息隊列來對請求做排隊處理,這樣可以把前端的請求的峰值給“削平”了,所謂削峰填谷。而后端通過自己能夠處理的速度來處理請求。這樣可以增加系統(tǒng)的吞吐量,但是實時性就會有影響。同時,還會引入消息丟失的問題,所以要對消息做持久化,這會造成“有狀態(tài)”的結(jié)點,從而增加了服務(wù)調(diào)度的難度。
數(shù)據(jù)分區(qū)和數(shù)據(jù)鏡像。數(shù)據(jù)分區(qū)是把數(shù)據(jù)按一定的方式分成多個區(qū)(比如通過地理位置),不同的數(shù)據(jù)區(qū)來分擔(dān)不同區(qū)的流量。這需要一個數(shù)據(jù)路由的中間件,而數(shù)據(jù)鏡像是把一個數(shù)據(jù)庫鏡像成多份一樣的數(shù)據(jù),這樣就不需要數(shù)據(jù)路由的中間件了。可以在任意結(jié)點上進行讀寫,內(nèi)部會自行同步數(shù)據(jù)。然而,數(shù)據(jù)鏡像中最大的問題就是數(shù)據(jù)的一致性問題。
提高架構(gòu)的穩(wěn)定性
接下來,咱們再來看看提高系統(tǒng)系統(tǒng)穩(wěn)定性的一些常用技術(shù)。

服務(wù)拆分。服務(wù)拆分主要有兩個目的:一是為了隔離故障,二是為了重用服務(wù)模塊。但服務(wù)拆分完之后,會引入服務(wù)調(diào)用間的依賴問題。
服務(wù)冗余。 服務(wù)冗余是為了去除單點故障,并可以支持服務(wù)的彈性伸縮,以及故障遷移。然而,對于一些有狀態(tài)的服務(wù)來說,冗余這些有狀態(tài)的服務(wù)帶來了更高的復(fù)雜性。其中一個是彈性伸縮時,需要考慮數(shù)據(jù)的復(fù)制或是重新分片,遷移的時候還要遷移數(shù)據(jù)到其它機器上。
限流降級。當(dāng)系統(tǒng)實在扛不住壓力時,只能通過限流或者功能降級的方式來停掉一部分服務(wù),或是拒絕一部分用戶,以確保整個架構(gòu)不會掛掉。這些技術(shù)屬于保護措施。
高可用架構(gòu)。通常來說高可用架構(gòu)是從冗余架構(gòu)的角度來保障可用性。比如,多租戶隔離,災(zāi)備多活,或是數(shù)據(jù)可以在其中復(fù)制保持一致性的集群??傊?,就是為了不出單點故障。
高可用運維。高可用運維指的是 DevOps 中的 CI/CD(持續(xù)集成 / 持續(xù)部署)。一個良好的運維應(yīng)該是一條很流暢的軟件發(fā)布管線,其中做了足夠的自動化測試,還可以做相應(yīng)的灰度發(fā)布,以及對線上系統(tǒng)的自動化控制。這樣,可以做到“計劃內(nèi)”或是“非計劃內(nèi)”的宕機事件的時長最短。上述這些技術(shù)非常有技術(shù)含量,而且需要投入大量的時間和精力。
正如不想當(dāng)將軍的士兵不是好士兵,不想當(dāng)架構(gòu)師的程序員不是一個好的程序員,哈哈,道阻且長,慢慢加油吧。?




























