高併發,幾乎是每個程式設計師都想擁有的經驗。原因很簡單:隨著流量變大,在遊戲陪玩app開發中會遇到各種各樣的技術問題,比如介面響應超時、CPU load升高、GC頻繁、死鎖、大資料量儲存等等,這些問題能推動我們在技術深度上不斷精進。
在過往的面試中,如果候選人做過高併發的專案,我通常會讓對方談談對於高併發的理解,但是能系統性地回答好此問題的人並不多,大概分成這樣幾類:
1、對資料化的指標沒有概念:不清楚選擇什麼樣的指標來衡量高併發系統?分不清併發量和QPS,甚至不知道遊戲陪玩app開發中的總使用者量、活躍使用者量,平峰和高峰時的QPS和TPS等關鍵資料。
2、設計了一些方案,但是細節掌握不透徹:講不出遊戲陪玩app開發高併發系統要關注的技術點和可能帶來的副作用。比如讀效能有瓶頸會引入快取,但是忽視了快取命中率、熱點key、資料一致性等問題。
3、理解片面,把高併發設計等同於遊戲陪玩app開發效能優化:大談併發程式設計、多級快取、非同步化、水平擴容,卻忽視高可用設計、服務治理和運維保障。
4、掌握大方案,卻忽視最基本的東西:能講清楚垂直分層、水平分割槽、快取等大思路,卻沒意識去分析資料結構是否合理,演算法是否高效,沒想過從最根本的IO和計算兩個維度去做遊戲陪玩app開發細節優化。
這篇文章,我想結合自己的高併發專案經驗,系統性地總結下高併發需要掌握的知識和實踐思路,希望對你有所幫助。內容分成以下3個部分:
- 如何理解高併發?
- 高併發系統設計的目標是什麼?
- 高併發的實踐方案有哪些?
01 如何理解高併發?
高併發意味著大流量,需要在遊戲陪玩app開發中運用技術手段抵抗流量的衝擊,這些手段好比操作流量,能讓流量更平穩地被系統所處理,帶給使用者更好的體驗。
我們常見的高併發場景有:淘寶的雙11、春運時的搶票、微博大V的熱點新聞等。除了這些典型事情,每秒幾十萬請求的秒殺系統、每天千萬級的訂單系統、每天億級日活的資訊流系統等,都可以歸為高併發。
很顯然,上面談到的高併發場景,併發量各不相同,那到底多大併發才算高併發呢?
1、不能只看數字,要看遊戲陪玩app開發具體的業務場景。不能說10W QPS的秒殺是高併發,而1W QPS的資訊流就不是高併發。資訊流場景涉及複雜的推薦模型和各種人工策略,它的業務邏輯可能比秒殺場景複雜10倍不止。因此,不在同一個維度,沒有任何比較意義。
2、遊戲陪玩app開發業務都是從0到1做起來的,併發量和QPS只是參考指標,最重要的是:在業務量逐漸變成原來的10倍、100倍的過程中,你是否用到了高併發的處理方法去演進你的系統,從架構設計、編碼實現、甚至產品方案等維度去預防和解決高併發引起的問題?而不是一味的升級硬體、加機器做水平擴充套件。
此外,遊戲陪玩app開發中各個高併發場景的業務特點完全不同:有讀多寫少的資訊流場景、有讀多寫多的交易場景,那是否有通用的技術方案解決不同場景的高併發問題呢?
我覺得大的思路可以借鑑,別人的方案也可以參考,但是真正落地過程中,細節上還會有無數的坑。另外,由於遊戲陪玩app開發軟硬體環境、技術棧、以及產品邏輯都沒法做到完全一致,這些都會導致同樣的業務場景,就算用相同的技術方案也會面臨不同的問題,這些坑還得一個個趟。
因此,這篇文章我會將重點放在基礎知識、通用思路、和我曾經實踐過的有效經驗上,希望讓你對高併發有更深的理解。
02 高併發系統設計的目標是什麼?
先搞清楚在遊戲陪玩app開發中高併發系統設計的目標,在此基礎上再討論設計方案和實踐經驗才有意義和針對性。
高併發絕不意味著只追求遊戲陪玩app開發高效能,這是很多人片面的理解。從巨集觀角度看,高併發系統設計的目標有三個:高效能、高可用,以及高可擴充套件。
1、高效能:遊戲陪玩app開發效能體現了系統的並行處理能力,在有限的硬體投入下,提高效能意味著節省成本。同時,效能也反映了使用者體驗,響應時間分別是100毫秒和1秒,給使用者的感受是完全不同的。
2、高可用:表示系統可以正常服務的時間。一個全年不停機、無故障;另一個隔三差五出線上事故、當機,使用者肯定選擇前者。另外,如果遊戲陪玩app開發系統只能做到90%可用,也會大大拖累業務。
3、高擴充套件:表示系統的擴充套件能力,流量高峰時能否在短時間內完成遊戲陪玩app開發擴容,更平穩地承接峰值流量,比如雙11活動、明星離婚等熱點事件。
這3個目標是需要通盤考慮的,因為它們互相關聯、甚至也會相互影響。
比如說:考慮遊戲陪玩app開發系統的擴充套件能力,你會將服務設計成無狀態的,這種叢集設計保證了高擴充套件性,其實也間接提升了系統的效能和可用性。
再比如說:為了保證遊戲陪玩app開發的可用性,通常會對服務介面進行超時設定,以防大量執行緒阻塞在慢請求上造成系統雪崩,那超時時間設定成多少合理呢?一般,我們會參考依賴服務的效能表現進行設定。
再從微觀角度來看,高效能、高可用和高擴充套件又有哪些具體的指標來衡量?為什麼會選擇這些指標呢?
通過效能指標可以度量遊戲陪玩app開發目前存在的效能問題,同時作為效能優化的評估依據。一般來說,會採用一段時間內的介面響應時間作為指標。
1、平均響應時間:最常用,但是缺陷很明顯,對於慢請求不敏感。比如1萬次請求,其中9900次是1ms,100次是100ms,則平均響應時間為1.99ms,雖然平均耗時僅增加了0.99ms,但是1%請求的響應時間已經增加了100倍。
2、TP90、TP99等分位值:將遊戲陪玩app開發的響應時間按照從小到大排序,TP90表示排在第90分位的響應時間, 分位值越大,對慢請求越敏感。
3、吞吐量:和響應時間呈反比,比如響應時間是1ms,則吞吐量為每秒1000次。
通常,遊戲陪玩app開發時設定效能目標會兼顧吞吐量和響應時間,比如這樣表述:在每秒1萬次請求下,AVG控制在50ms以下,TP99控制在100ms以下。對於高併發系統,AVG和TP分位值必須同時要考慮。
另外,從使用者體驗角度來看,200毫秒被認為是第一個分界點,使用者感覺不到延遲,1秒是第二個分界點,使用者能感受到延遲,但是可以接受。
因此,對於一個健康的遊戲陪玩app開發的高併發系統,TP99應該控制在200毫秒以內,TP999或者TP9999應該控制在1秒以內。
高可用性是指遊戲陪玩app開發系統具有較高的無故障執行能力,可用性 = 正常執行時間 / 系統總執行時間,一般使用幾個9來描述系統的可用性。
對於遊戲陪玩app開發的高併發系統來說,最基本的要求是:保證3個9或者4個9。原因很簡單,如果你只能做到2個9,意味著有1%的故障時間,像一些大公司每年動輒千億以上的GMV或者收入,1%就是10億級別的業務影響。
面對突發流量,不可能臨時改造架構,最快的方式就是增加機器來線性提高系統的處理能力。
對於遊戲陪玩app開發的業務叢集或者基礎元件來說,擴充套件性 = 效能提升比例 / 機器增加比例,理想的擴充套件能力是:資源增加幾倍,效能提升幾倍。通常來說,擴充套件能力要維持在70%以上。
但是從高併發系統的整體架構角度來看,擴充套件的目標不僅僅是把遊戲陪玩app開發服務設計成無狀態就行了,因為當流量增加10倍,業務服務可以快速擴容10倍,但是資料庫可能就成為了新的瓶頸。
像遊戲陪玩app開發中MySQL這種有狀態的儲存服務通常是擴充套件的技術難點,如果架構上沒提前做好規劃(垂直和水平拆分),就會涉及到大量資料的遷移。
因此,高擴充套件性需要考慮:遊戲陪玩app開發的服務叢集、資料庫、快取和訊息佇列等中介軟體、負載均衡、頻寬、依賴的第三方等,當併發達到某一個量級後,上述每個因素都可能成為擴充套件的瓶頸點。
03 高併發的實踐方案有哪些?
瞭解了高併發設計的3大目標後,再系統性總結下游戲陪玩app開發中高併發的設計方案,會從以下兩部分展開:先總結下通用的設計方法,然後再圍繞高效能、高可用、高擴充套件分別給出具體的實踐方案。
通用的設計方法主要是從「縱向」和「橫向」兩個維度出發,俗稱高併發處理的兩板斧:縱向擴充套件和橫向擴充套件。
它的目標是提升遊戲陪玩app開發中單機的處理能力,方案又包括:
1、提升單機的硬體效能:通過增加記憶體、CPU核數、儲存容量、或者將磁碟升級成SSD等堆硬體的方式來提升。
2、提升單機的軟體效能:使用快取減少IO次數,使用併發或者非同步的方式增加吞吐量。
因為單機效能總會存在極限,所以最終還需要引入橫向擴充套件,通過遊戲陪玩app開發時的叢集部署以進一步提高併發處理能力,又包括以下2個方向:
1、做好分層架構:這是橫向擴充套件的提前,因為遊戲陪玩app開發的高併發系統往往業務複雜,通過分層處理可以簡化複雜問題,更容易做到橫向擴充套件。
上面這種圖是網際網路最常見的遊戲陪玩app開發分層架構,當然真實的高併發系統架構會在此基礎上進一步完善。比如會做動靜分離並引入CDN,反向代理層可以是LVS+Nginx,Web層可以是統一的API閘道器,業務服務層可進一步按垂直業務做微服務化,儲存層可以是各種異構資料庫。
2、各層進行水平擴充套件:無狀態水平擴容,有狀態做分片路由。遊戲陪玩app開發的業務叢集通常能設計成無狀態的,而資料庫和快取往往是有狀態的,因此需要設計分割槽鍵做好儲存分片,當然也可以通過主從同步、讀寫分離的方案提升讀效能。
下面再結合我的個人經驗,針對高效能、高可用、高擴充套件3個方面,總結下可落地的實踐方案。
1、叢集部署,通過負載均衡減輕遊戲陪玩app開發的單機壓力。
2、多級快取,包括靜態資料使用CDN、本地快取、分散式快取等,以及對快取場景中的熱點key、快取穿透、快取併發、資料一致性等問題的處理。
3、分庫分表和索引優化,以及藉助搜尋引擎解決遊戲陪玩app開發中複雜查詢問題。
4、考慮NoSQL資料庫的使用,比如HBase、TiDB等,但是團隊必須熟悉這些元件,且有較強的運維能力。
5、非同步化,將次要流程通過多執行緒、MQ、甚至延時任務進行非同步處理。
6、限流,需要先考慮業務是否允許限流(比如秒殺場景是允許的),包括前端限流、Nginx接入層的限流、服務端的限流。
7、對流量進行削峰填谷,通過MQ承接流量。
8、併發處理,通過多執行緒將序列邏輯並行化。
9、預計算,比如搶紅包場景,可以提前計算好紅包金額快取起來,發紅包時直接使用即可。
10、快取預熱,在遊戲陪玩app開發時通過非同步任務提前預熱資料到本地快取或者分散式快取中。
11、減少IO次數,比如資料庫和快取的批量讀寫、RPC的批量介面支援、或者通過冗餘資料的方式幹掉RPC呼叫。
12、減少IO時的資料包大小,包括採用輕量級的通訊協議、合適的資料結構、去掉介面中的多餘欄位、減少快取key的大小、壓縮快取value等。
13、程式邏輯優化,比如將遊戲陪玩app開發中大概率阻斷執行流程的判斷邏輯前置、For迴圈的計算邏輯優化,或者採用更高效的演算法。
14、各種池化技術的使用和池大小的設定,包括HTTP請求池、執行緒池(考慮CPU密集型還是IO密集型設定核心引數)、資料庫和Redis連線池等。
15、JVM優化,包括新生代和老年代的大小、GC演算法的選擇等,儘可能減少GC頻率和耗時。
16、鎖選擇,讀多寫少的場景用樂觀鎖,或者考慮通過分段鎖的方式減少鎖衝突。
上述方案無外乎從遊戲陪玩app開發的計算和 IO 兩個維度考慮所有可能的優化點,需要有配套的監控系統實時瞭解當前的效能表現,並支撐你進行效能瓶頸分析,然後再遵循二八原則,抓主要矛盾進行優化。
1、遊戲陪玩app開發中對等節點的故障轉移,Nginx和服務治理框架均支援一個節點失敗後訪問另一個節點。
2、非對等節點的故障轉移,通過心跳檢測並實施主備切換(比如redis的哨兵模式或者叢集模式、MySQL的主從切換等)。
3、介面層面的超時設定、重試策略和冪等設計。
4、降級處理:保證遊戲陪玩app開發的核心服務,犧牲非核心服務,必要時進行熔斷;或者核心鏈路出問題時,有備選鏈路。
5、限流處理:對超過系統處理能力的請求直接拒絕或者返回錯誤碼。
6、MQ場景的訊息可靠性保證,包括producer端的重試機制、broker側的持久化、consumer端的ack機制等。
7、灰度釋出,能支援按機器維度進行小流量部署,觀察系統日誌和業務指標,等執行平穩後再推全量。
8、監控報警:遊戲陪玩app開發全方位的監控體系,包括最基礎的CPU、記憶體、磁碟、網路的監控,以及Web伺服器、JVM、資料庫、各類中介軟體的監控和業務指標的監控。
9、災備演練:類似當前的“混沌工程”,對系統進行一些破壞性手段,觀察區域性故障是否會引起可用性問題。
遊戲陪玩app開發高可用的方案主要從冗餘、取捨、系統運維3個方向考慮,同時需要有配套的值班機制和故障處理流程,當出現線上問題時,可及時跟進處理。
1、合理的分層架構:比如上面談到的網際網路最常見的分層架構,另外還能進一步按照資料訪問層、業務邏輯層對微服務做更細粒度的分層(但是需要評估效能,會存在網路多一跳的情況)。
2、儲存層的拆分:按照遊戲陪玩app開發業務維度做垂直拆分、按照資料特徵維度進一步做水平拆分(分庫分表)。
3、業務層的拆分:最常見的是按照業務維度拆(比如電商場景的商品服務、訂單服務等),也可以按照核心介面和非核心介面拆,還可以按照請求源拆(比如To C和To B,APP和H5)。
最後的話
高併發確實是一個複雜且系統性的問題,由於篇幅有限,諸如分散式Trace、全鏈路壓測、柔性事務都是要考慮的技術點。另外,如果遊戲陪玩app開發的業務場景不同,高併發的落地方案也會存在差異,但是總體的設計思路和可借鑑的方案基本類似。
遊戲陪玩app開發實現高併發設計同樣要秉承架構設計的3個原則:簡單、合適和演進。“過早的優化是萬惡之源”,不能脫離遊戲陪玩app開發業務的實際情況,更不要過度設計,合適的方案就是最完美的。
本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
原文連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2842931/,如需轉載,請註明出處,否則將追究法律責任。