天天看點

資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

一  前言

高并發,幾乎是每個程式員都想擁有的經驗。原因很簡單:随着流量變大,會遇到各種各樣的技術問題,比如接口響應逾時、CPU load升高、GC頻繁、死鎖、大資料量存儲等等,這些問題能推動我們在技術深度上不斷精進。

在過往的面試中,如果候選人做過高并發的項目,我通常會讓對方談談對于高并發的了解,但是能系統性地回答好此問題的人并不多,大概分成這樣幾類:

1、對資料化的名額沒有概念:不清楚選擇什麼樣的名額來衡量高并發系統?分不清并發量和QPS,甚至不知道自己系統的總使用者量、活躍使用者量,平峰和高峰時的QPS和TPS等關鍵資料。

2、設計了一些方案,但是細節掌握不透徹:講不出該方案要關注的技術點和可能帶來的副作用。比如讀性能有瓶頸會引入緩存,但是忽視了緩存命中率、熱點key、資料一緻性等問題。

3、了解片面,把高并發設計等同于性能優化:大談并發程式設計、多級緩存、異步化、水準擴容,卻忽視高可用設計、服務治理和運維保障。

4、掌握大方案,卻忽視最基本的東西:能講清楚垂直分層、水準分區、緩存等大思路,卻沒意識去分析資料結構是否合理,算法是否高效,沒想過從最根本的IO和計算兩個次元去做細節優化。

5、掌握了技術方案,卻忽視了業務分析:能講清楚高并發的技術方案,卻沒有事先對業務需求進行分析而忽略本質(系統是否是高并發系統,系統是CA類型還是CP類型,系統容量如何規劃的)、降低成本提升效能。

這篇文章,我想結合自己的高并發項目經驗,系統性地總結下高并發需要掌握的知識和實踐思路,希望對你有所幫助。内容分成以下3個部分:

  • 如何了解高并發?
  • 高并發系統設計的目标是什麼?
  • 高并發的實踐方案有哪些?
資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

二  如何了解高并發?

高并發意味着大流量,需要運用技術手段抵抗流量的沖擊,這些手段好比操作流量,能讓流量更平穩地被系統所處理,帶給使用者更好的體驗。我們常見的高并發場景有:淘寶的雙11、春運時的搶票、微網誌大V的熱點新聞等。除了這些典型事情,每秒幾十萬請求的秒殺系統、每天千萬級的訂單系統、每天億級日活的資訊流系統等,都可以歸為高并發。

很顯然,上面談到的高并發場景,并發量各不相同,那到底多大并發才算高并發呢?

1、不能隻看數字,要看具體的業務場景。不能說10W QPS的秒殺是高并發,而1W QPS的資訊流就不是高并發。資訊流場景涉及複雜的推薦模型和各種人工政策,它的業務邏輯可能比秒殺場景複雜10倍不止。是以,不在同一個次元,沒有任何比較意義。

2、業務都是從0到1做起來的,并發量和QPS隻是參考名額,最重要的是:在業務量逐漸變成原來的10倍、100倍的過程中,你是否用到了高并發的處理方法去演進你的系統,從架構設計、編碼實作、甚至産品方案等次元去預防和解決高并發引起的問題?而不是一味的更新硬體、加機器做水準擴充。

此外,各個高并發場景的業務特點完全不同:有讀多寫少的資訊流場景、有讀多寫多的交易場景,那是否有通用的技術方案解決不同場景的高并發問題呢?

我覺得大的思路可以借鑒,别人的方案也可以參考,但是真正落地過程中,細節上還會有無數的坑。另外,由于軟硬體環境、技術棧、以及産品邏輯都沒法做到完全一緻,這些都會導緻同樣的業務場景,就算用相同的技術方案也會面臨不同的問題,這些坑還得一個個趟。

是以,這篇文章我會将重點放在基礎知識、通用思路、和我曾經實踐過的有效經驗上,希望讓你對高并發有更深的了解。

資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

三 高并發系統設計的目标是什麼?

資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

先搞清楚高并發系統設計的目标,在此基礎上再讨論設計方案和實踐經驗才有意義和針對性。

2.1 宏觀目标

高并發絕不意味着隻追求高性能,這是很多人片面的了解。從宏觀角度看,高并發系統設計的目标有三個:高性能、高可用,以及高可擴充。

  • 高性能:性能展現了系統的并行處理能力,在有限的硬體投入下,提高性能意味着節省成本。同時,性能也反映了使用者體驗,響應時間分别是100毫秒和1秒,給使用者的感受是完全不同的。
  • 高可用:表示系統可以正常服務的時間。一個全年不停機、無故障;另一個隔三差五出線上事故、當機,使用者肯定選擇前者。另外,如果系統隻能做到90%可用,也會大大拖累業務。
  • 高擴充:表示系統的擴充能力,流量高峰時能否在短時間内完成擴容,更平穩地承接峰值流量,比如雙11活動、明星離婚等熱點事件。
資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

這3個目标是需要通盤考慮的,因為它們互相關聯、甚至也會互相影響。比如說:考慮系統的擴充能力,你會将服務設計成無狀态的,這種叢集設計保證了高擴充性,其實也間接提升了系統的性能和可用性。再比如說:為了保證可用性,通常會對服務接口進行逾時設定,以防大量線程阻塞在慢請求上造成系統雪崩,那逾時時間設定成多少合理呢?一般,我們會參考依賴服務的性能表現進行設定。

2.2 微觀目标

再從微觀角度來看,高性能、高可用和高擴充又有哪些具體的名額來衡量?為什麼會選擇這些名額呢?

1)性能名額

通過性能名額可以度量目前存在的性能問題,同時作為性能優化的評估依據。一般來說,會采用一段時間内的接口響應時間作為名額。

平均響應時間:最常用,但是缺陷很明顯,對于慢請求不敏感。比如1萬次請求,其中9900次是1ms,100次是100ms,則平均響應時間為1.99ms,雖然平均耗時僅增加了0.99ms,但是1%請求的響應時間已經增加了100倍。

TP90、TP99等分位值:将響應時間按照從小到大排序,TP90表示排在第90分位的響應時間, 分位值越大,對慢請求越敏感。

資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

吞吐量:和響應時間呈反比,比如響應時間是1ms,則吞吐量為每秒1000次。通常,設定性能目标時會兼顧吞吐量和響應時間,比如這樣表述:在每秒1萬次請求下,AVG控制在50ms以下,TP99控制在100ms以下。對于高并發系統,AVG和TP分位值必須同時要考慮。

另外,從使用者體驗角度來看,200毫秒被認為是第一個分界點,使用者感覺不到延遲,1秒是第二個分界點,使用者能感受到延遲,但是可以接受。

是以,對于一個健康的高并發系統,TP99應該控制在200毫秒以内,TP999或者TP9999應該控制在1秒以内。

2)可用性名額

高可用性是指系統具有較高的無故障運作能力,可用性 = 正常運作時間 / 系統總運作時間,一般使用幾個9來描述系統的可用性。

資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

對于高并發系統來說,最基本的要求是:保證3個9或者4個9。原因很簡單,如果你隻能做到2個9,意味着有1%的故障時間,像一些大公司每年動辄千億以上的GMV或者收入,1%就是10億級别的業務影響。

3)可擴充性名額

面對突發流量,不可能臨時改造架構,最快的方式就是增加機器來線性提高系統的處理能力。

對于業務叢集或者基礎元件來說,擴充性 = 性能提升比例 / 機器增加比例,理想的擴充能力是:資源增加幾倍,性能提升幾倍。通常來說,擴充能力要維持在70%以上。

但是從高并發系統的整體架構角度來看,擴充的目标不僅僅是把服務設計成無狀态就行了,因為當流量增加10倍,業務服務可以快速擴容10倍,但是資料庫可能就成為了新的瓶頸。

像MySQL這種有狀态的存儲服務通常是擴充的技術難點,如果架構上沒提前做好規劃(垂直和水準拆分),就會涉及到大量資料的遷移。

是以,高擴充性需要考慮:服務叢集、資料庫、緩存和消息隊列等中間件、負載均衡、帶寬、依賴的第三方等,當并發達到某一個量級後,上述每個因素都可能成為擴充的瓶頸點。

資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

三 高并發的實踐方案有哪些?

了解了高并發設計的3大目标後,再系統性總結下高并發的設計方案,會從以下兩部分展開:先總結下通用的設計方法,然後再圍繞高性能、高可用、高擴充分别給出具體的實踐方案。

3.1 通用的設計方法二級标

通用的設計方法主要是從「縱向」和「橫向」兩個次元出發,俗稱高并發處理的兩闆斧:縱向擴充和橫向擴充。

1)縱向擴充(scale-up)

它的目标是提升單機的處理能力,方案又包括:

  • 提升單機的硬體性能:通過增加記憶體、CPU核數、存儲容量、或者将磁盤更新成SSD等堆硬體的方式來提升。
  • 提升單機的軟體性能:使用緩存減少IO次數,使用并發或者異步的方式增加吞吐量。

2)橫向擴充(scale-out)

因為單機性能總會存在極限,是以最終還需要引入橫向擴充,通過叢集部署以進一步提高并發處理能力,又包括以下2個方向:

  • 做好分層架構:這是橫向擴充的提前,因為高并發系統往往業務複雜,通過分層處理可以簡化複雜問題,更容易做到橫向擴充。
資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

上面這種圖是網際網路最常見的分層架構,當然真實的高并發系統架構會在此基礎上進一步完善。比如會做動靜分離并引入CDN,反向代理層可以是LVS+Nginx,Web層可以是統一的API網關,業務服務層可進一步按垂直業務做微服務化,存儲層可以是各種異構資料庫。

  • 各層進行水準擴充:無狀态水準擴容,有狀态做分片路由。業務叢集通常能設計成無狀态的,而資料庫和緩存往往是有狀态的,是以需要設計分區鍵做好存儲分片,當然也可以通過主從同步、讀寫分離的方案提升讀性能。

3.2 具體的實踐方案

下面再結合我的個人經驗,針對高性能、高可用、高擴充3個方面,總結下可落地的實踐方案。

1)高性能的實踐方案

叢集部署,通過負載均衡減輕單機壓力。

多級緩存,包括靜态資料使用CDN、本地緩存、分布式緩存等,以及對緩存場景中的熱點key、緩存穿透、緩存并發、資料一緻性等問題的處理。

分庫分表和索引優化,以及借助搜尋引擎解決複雜查詢問題。

考慮NoSQL資料庫的使用,比如HBase、TiDB等,但是團隊必須熟悉這些元件,且有較強的運維能力。

異步化,将次要流程通過多線程、MQ、甚至延時任務進行異步處理。

限流,需要先考慮業務是否允許限流(比如秒殺場景是允許的),包括前端限流、Nginx接入層的限流、服務端的限流。

對流量進行削峰填谷,通過MQ承接流量。

并發處理,通過多線程将串行邏輯并行化。

預計算,比如搶紅包場景,可以提前計算好紅包金額緩存起來,發紅包時直接使用即可。

存預熱,通過異步任務提前預熱資料到本地緩存或者分布式緩存中。

減少IO次數,比如資料庫和緩存的批量讀寫、RPC的批量接口支援、或者通過備援資料的方式幹掉RPC調用。

減少IO時的資料包大小,包括采用輕量級的通信協定、合适的資料結構、去掉接口中的多餘字段、減少緩存key的大小、壓縮緩存value等。

程式邏輯優化,比如将大機率阻斷執行流程的判斷邏輯前置、For循環的計算邏輯優化,或者采用更高效的算法。

各種池化技術的使用和池大小的設定,包括HTTP請求池、線程池(考慮CPU密集型還是IO密集型設定核心參數)、資料庫和Redis連接配接池等。

JVM優化,包括新生代和老年代的大小、GC算法的選擇等,盡可能減少GC頻率和耗時。

鎖選擇,讀多寫少的場景用樂觀鎖,或者考慮通過分段鎖的方式減少鎖沖突。

上述方案無外乎從計算和 IO 兩個次元考慮所有可能的優化點,需要有配套的監控系統實時了解目前的性能表現,并支撐你進行性能瓶頸分析,然後再遵循二八原則,抓主要沖突進行優化。

2)高可用的實踐方案

對等節點的故障轉移,Nginx和服務治理架構均支援一個節點失敗後通路另一個節點。

非對等節點的故障轉移,通過心跳檢測并實施主備切換(比如redis的哨兵模式或者叢集模式、MySQL的主從切換等)。

接口層面的逾時設定、重試政策和幂等設計。

降級處理:保證核心服務,犧牲非核心服務,必要時進行熔斷;或者核心鍊路出問題時,有備選鍊路。

限流處理:對超過系統處理能力的請求直接拒絕或者傳回錯誤碼。

MQ場景的消息可靠性保證,包括producer端的重試機制、broker側的持久化、consumer端的ack機制等。

灰階釋出,能支援按機器次元進行小流量部署,觀察系統日志和業務名額,等運作平穩後再推全量。

監控報警:全方位的監控體系,包括最基礎的CPU、記憶體、磁盤、網絡的監控,以及Web伺服器、JVM、資料庫、各類中間件的監控和業務名額的監控。

災備演練:類似目前的“混沌工程”,對系統進行一些破壞性手段,觀察局部故障是否會引起可用性問題。

高可用的方案主要從備援、取舍、系統運維3個方向考慮,同時需要有配套的值班機制和故障處理流程,當出現線上問題時,可及時跟進處理。

3)高擴充的實踐方案

合理的分層架構:比如上面談到的網際網路最常見的分層架構,另外還能進一步按照資料通路層、業務邏輯層對微服務做更細粒度的分層(但是需要評估性能,會存在網絡多一跳的情況)。

存儲層的拆分:按照業務次元做垂直拆分、按照資料特征次元進一步做水準拆分(分庫分表)。

業務層的拆分:最常見的是按照業務次元拆(比如電商場景的商品服務、訂單服務等),也可以按照核心接口和非核心接口拆,還可以按照請求源拆(比如To C和To B,APP和H5)。

資深架構師推薦--高并發的了解及名額的衡量一  前言二  如何了解高并發?三 高并發系統設計的目标是什麼?三 高并發的實踐方案有哪些?四 最後的話

四 最後的話

高并發确實是一個複雜且系統性的問題,由于篇幅有限,諸如分布式Trace、全鍊路壓測、柔性事務都是要考慮的技術點。另外,如果業務場景不同,高并發的落地方案也會存在差異,但是總體的設計思路和可借鑒的方案基本類似。

高并發設計同樣要秉承架構設計的3個原則:簡單、合适和演進。“過早的優化是萬惡之源”,不能脫離業務的實際情況,更不要過度設計,合适的方案就是最完美的。

希望這篇文章能帶給你關于高并發更全面的認識,如果你也有可借鑒的經驗和深入的思考,歡迎評論區留言讨論。

繼續閱讀