您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么理解web開發中的高并發”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么理解web開發中的高并發”吧!
如何理解高并發?
高并發意味著大流量,需要運用技術手段抵抗流量的沖擊,這些手段好比操作流量,能讓流量更平穩地被系統所處理,帶給用戶更好的體驗。
我們常見的高并發場景有:淘寶的雙 11、春運時的搶票、微博大 V 的熱點新聞等。
除了這些典型事情,每秒幾十萬請求的秒殺系統、每天千萬級的訂單系統、每天億級日活的信息流系統等,都可以歸為高并發。
很顯然,上面談到的高并發場景,并發量各不相同,那到底多大并發才算高并發呢?
①不能只看數字,要看具體的業務場景。不能說 10W QPS 的秒殺是高并發,而 1W QPS 的信息流就不是高并發。
信息流場景涉及復雜的推薦模型和各種人工策略,它的業務邏輯可能比秒殺場景復雜 10 倍不止。因此,不在同一個維度,沒有任何比較意義。
②業務都是從 0 到 1 做起來的,并發量和 QPS 只是參考指標,最重要的是:在業務量逐漸變成原來的 10 倍、100 倍的過程中,你是否用到了高并發的處理方法去演進你的系統。
從架構設計、編碼實現、甚至產品方案等維度去預防和解決高并發引起的問題?而不是一味的升級硬件、加機器做水平擴展。
此外,各個高并發場景的業務特點完全不同:有讀多寫少的信息流場景、有讀多寫多的交易場景,那是否有通用的技術方案解決不同場景的高并發問題呢?
我覺得大的思路可以借鑒,別人的方案也可以參考,但是真正落地過程中,細節上還會有無數的坑。
另外,由于軟硬件環境、技術棧、以及產品邏輯都沒法做到完全一致,這些都會導致同樣的業務場景,就算用相同的技術方案也會面臨不同的問題,這些坑還得一個個趟。
因此,這篇文章我會將重點放在基礎知識、通用思路、和我曾經實踐過的有效經驗上,希望讓你對高并發有更深的理解。
高并發系統設計的目標是什么?
先搞清楚高并發系統設計的目標,在此基礎上再討論設計方案和實踐經驗才有意義和針對性。
宏觀目標
高并發絕不意味著只追求高性能,這是很多人片面的理解。從宏觀角度看,高并發系統設計的目標有三個:高性能、高可用,以及高可擴展。
①高性能:性能體現了系統的并行處理能力,在有限的硬件投入下,提高性能意味著節省成本。
同時,性能也反映了用戶體驗,響應時間分別是 100 毫秒和 1 秒,給用戶的感受是完全不同的。
②高可用:表示系統可以正常服務的時間。一個全年不停機、無故障;另一個隔三差五出線上事故、宕機,用戶肯定選擇前者。另外,如果系統只能做到 90% 可用,也會大大拖累業務。
③高擴展:表示系統的擴展能力,流量高峰時能否在短時間內完成擴容,更平穩地承接峰值流量,比如雙 11 活動、明星離婚等熱點事件。
這 3 個目標是需要通盤考慮的,因為它們互相關聯、甚至也會相互影響。
比如說:考慮系統的擴展能力,你會將服務設計成無狀態的,這種集群設計保證了高擴展性,其實也間接提升了系統的性能和可用性。
再比如說:為了保證可用性,通常會對服務接口進行超時設置,以防大量線程阻塞在慢請求上造成系統雪崩,那超時時間設置成多少合理呢?一般,我們會參考依賴服務的性能表現進行設置。
微觀目標
再從微觀角度來看,高性能、高可用和高擴展又有哪些具體的指標來衡量?為什么會選擇這些指標呢?
性能指標:通過性能指標可以度量目前存在的性能問題,同時作為性能優化的評估依據。一般來說,會采用一段時間內的接口響應時間作為指標。
①平均響應時間:最常用,但是缺陷很明顯,對于慢請求不敏感。比如 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 秒以內。
可用性指標:高可用性是指系統具有較高的無故障運行能力,可用性=平均故障時間/系統總運行時間,一般使用幾個 9 來描述系統的可用性。
對于高并發系統來說,最基本的要求是:保證 3 個 9 或者 4 個 9。原因很簡單,如果你只能做到 2 個 9,意味著有 1% 的故障時間,像一些大公司每年動輒千億以上的 GMV 或者收入,1% 就是 10 億級別的業務影響。
可擴展性指標:面對突發流量,不可能臨時改造架構,最快的方式就是增加機器來線性提高系統的處理能力。
對于業務集群或者基礎組件來說,擴展性=性能提升比例/機器增加比例,理想的擴展能力是:資源增加幾倍,性能提升幾倍。通常來說,擴展能力要維持在 70% 以上。
但是從高并發系統的整體架構角度來看,擴展的目標不僅僅是把服務設計成無狀態就行了,因為當流量增加 10 倍,業務服務可以快速擴容 10 倍,但是數據庫可能就成為了新的瓶頸。
像 MySQL 這種有狀態的存儲服務通常是擴展的技術難點,如果架構上沒提前做好規劃(垂直和水平拆分),就會涉及到大量數據的遷移。
因此,高擴展性需要考慮:服務集群、數據庫、緩存和消息隊列等中間件、負載均衡、帶寬、依賴的第三方等,當并發達到某一個量級后,上述每個因素都可能成為擴展的瓶頸點。
高并發的實踐方案有哪些?
了解了高并發設計的 3 大目標后,再系統性總結下高并發的設計方案,會從以下兩部分展開:先總結下通用的設計方法,然后再圍繞高性能、高可用、高擴展分別給出具體的實踐方案。
通用的設計方法
通用的設計方法主要是從「縱向」和「橫向」兩個維度出發,俗稱高并發處理的兩板斧:縱向擴展和橫向擴展。
縱向擴展(scale-up):它的目標是提升單機的處理能力。
方案包括如下兩種:
提升單機的硬件性能:通過增加內存、CPU 核數、存儲容量、或者將磁盤升級成 SSD 等堆硬件的方式來提升。
提升單機的軟件性能:使用緩存減少 IO 次數,使用并發或者異步的方式增加吞吐量。
橫向擴展(scale-out):因為單機性能總會存在極限,所以最終還需要引入橫向擴展,通過集群部署以進一步提高并發處理能力。
包括以下兩個方向:
①做好分層架構:這是橫向擴展的提前,因為高并發系統往往業務復雜,通過分層處理可以簡化復雜問題,更容易做到橫向擴展。
上面這種圖是互聯網最常見的分層架構,當然真實的高并發系統架構會在此基礎上進一步完善。
比如會做動靜分離并引入 CDN,反向代理層可以是 LVS+Nginx,Web 層可以是統一的 API 網關,業務服務層可進一步按垂直業務做微服務化,存儲層可以是各種異構數據庫。
②各層進行水平擴展:無狀態水平擴容,有狀態做分片路由。業務集群通常能設計成無狀態的,而數據庫和緩存往往是有狀態的,因此需要設計分區鍵做好存儲分片,當然也可以通過主從同步、讀寫分離的方案提升讀性能。
具體的實踐方案
下面再結合我的個人經驗,針對高性能、高可用、高擴展 3 個方面,總結下可落地的實踐方案。
高性能的實踐方案:
集群部署,通過負載均衡減輕單機壓力。
多級緩存,包括靜態數據使用 CDN、本地緩存、分布式緩存等,以及對緩存場景中的熱點 Key、緩存穿透、緩存并發、數據一致性等問題的處理。
分庫分表和索引優化,以及借助搜索引擎解決復雜查詢問題。
考慮 NoSQL 數據庫的使用,比如 HBase、TiDB 等,但是團隊必須熟悉這些組件,且有較強的運維能力。
異步化,將次要流程通過多線程、MQ、甚至延時任務進行異步處理。
限流,需要先考慮業務是否允許限流(比如秒殺場景是允許的),包括前端限流、Nginx 接入層的限流、服務端的限流。
對流量進行削峰填谷,通過 MQ 承接流量。
并發處理,通過多線程將串行邏輯并行化。
預計算,比如搶紅包場景,可以提前計算好紅包金額緩存起來,發紅包時直接使用即可。
緩存預熱,通過異步任務提前預熱數據到本地緩存或者分布式緩存中。
減少 IO 次數,比如數據庫和緩存的批量讀寫、RPC 的批量接口支持、或者通過冗余數據的方式干掉 RPC 調用。
減少 IO 時的數據包大小,包括采用輕量級的通信協議、合適的數據結構、去掉接口中的多余字段、減少緩存 Key 的大小、壓縮緩存 Value 等。
程序邏輯優化,比如將大概率阻斷執行流程的判斷邏輯前置、For 循環的計算邏輯優化,或者采用更高效的算法。
各種池化技術的使用和池大小的設置,包括 HTTP 請求池、線程池(考慮 CPU 密集型還是 IO 密集型設置核心參數)、數據庫和 Redis 連接池等。
JVM 優化,包括新生代和老年代的大小、GC 算法的選擇等,盡可能減少 GC 頻率和耗時。
鎖選擇,讀多寫少的場景用樂觀鎖,或者考慮通過分段鎖的方式減少鎖沖突。
上述方案無外乎從計算和 IO 兩個維度考慮所有可能的優化點,需要有配套的監控系統實時了解當前的性能表現,并支撐你進行性能瓶頸分析,然后再遵循二八原則,抓主要矛盾進行優化。
高可用的實踐方案:
對等節點的故障轉移,Nginx 和服務治理框架均支持一個節點失敗后訪問另一個節點。
非對等節點的故障轉移,通過心跳檢測并實施主備切換(比如redis的哨兵模式或者集群模式、MySQL 的主從切換等)。
接口層面的超時設置、重試策略和冪等設計。
降級處理:保證核心服務,犧牲非核心服務,必要時進行熔斷;或者核心鏈路出問題時,有備選鏈路。
限流處理:對超過系統處理能力的請求直接拒絕或者返回錯誤碼。
MQ 場景的消息可靠性保證,包括 Producer 端的重試機制、Broker 側的持久化、Consumer 端的 Ack 機制等。
灰度發布,能支持按機器維度進行小流量部署,觀察系統日志和業務指標,等運行平穩后再推全量。
監控報警:全方位的監控體系,包括最基礎的 CPU、內存、磁盤、網絡的監控,以及 Web 服務器、JVM、數據庫、各類中間件的監控和業務指標的監控。
災備演練:類似當前的“混沌工程”,對系統進行一些破壞性手段,觀察局部故障是否會引起可用性問題。
高可用的方案主要從冗余、取舍、系統運維 3 個方向考慮,同時需要有配套的值班機制和故障處理流程,當出現線上問題時,可及時跟進處理。
高擴展的實踐方案:
合理的分層架構:比如上面談到的互聯網最常見的分層架構,另外還能進一步按照數據訪問層、業務邏輯層對微服務做更細粒度的分層(但是需要評估性能,會存在網絡多一跳的情況)。
存儲層的拆分:按照業務維度做垂直拆分、按照數據特征維度進一步做水平拆分(分庫分表)。
業務層的拆分:最常見的是按照業務維度拆(比如電商場景的商品服務、訂單服務等),也可以按照核心接口和非核心接口拆,還可以按照請求源拆(比如 To C 和 To B,APP 和 H5)。
感謝各位的閱讀,以上就是“怎么理解web開發中的高并發”的內容了,經過本文的學習后,相信大家對怎么理解web開發中的高并發這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。