大廠都是如何對高并發系統做性能優化的?
1 導讀
高并發系統的奧義:高性能、高可用、可擴展。
性能反應了系統的使用體驗
都是上萬QPS的系統,一個響應時間毫秒級,一個秒級,用戶體驗明顯不同
可用性則表示系統可以正常服務用戶的時間
上萬QPS的系統,一個可全年不停機且無異常,一個隔三差五就宕機
可擴展性
流量可分為平時流量、峰值流量。峰值流量可能會是平時流量的幾倍至幾十倍,在應對峰值流量時,通常需在架構方案上做更多準備。易于擴展的系統能在短期內迅速擴容,更加平穩分攤峰值流量。
業務價值->承載高并發->性能優化。
一切的前提是業務價值需要。如果沒有足夠價值,那可讀性才是第一,性能在需要的地方是no.1,但不需要的地方可能就是倒數第一。當下技術框架出來的軟件差不到哪去,沒有這種及時響應訴求的地方,削峰下慢慢跑就是了。(但工作中常需要在缺少價值的地方著手性能優化。異步,并發編程,邏輯緩存,算法真的會加劇系統的復雜度,得不償失。如果沒那個價值,簡單才是王道)。
提高并發度
要么加硬件
要么降低服務響應時間
做為開發,我們的目光更聚焦在降低響應時間:
1.采用非阻塞的rpc調用(高效的遠端請求模式,采用容器的覆蓋網絡我認為也算)
2.將計算密集和io密集的的邏輯分割開,單獨線程池,調整線程比例壓榨單機性能(或者說找拐點)。
3.做緩存,io耗時的緩存和計算耗時的緩存(多級緩存,數據壓縮降低帶寬)。
4.采用享元模式,用好對象池和本地線程空間,盡量減少對象創建與銷毀的開銷,提高復用。
5.業務拆分,像狀態變化后的外部系統通知,業務監控,es或solr等副本數據同步等操作,無需在主流程中做的事都拆掉。走canal監聽表數據變化,推mq保最終一致的方式從業務項目完全解偶出來。
6.fork_join,分而治之的處理大任務。并發編程,采用多線程并行的方式處理業務。(規避偽共享,減小鎖力度,采用合適的鎖)。
7.數據庫配置優化,查詢優化。(存儲優化比較頭疼,畢竟不按業務拆單點跑不掉,單點性能就要命。基本只能內存庫先行,后臺同步數據做持久。然后內存庫多副本,自修復,保留一系列自修復失敗的修復手段)
2 性能優化原則
業務導向
脫離業務問題,妄自過早優化會徒增系統復雜度,浪費開發時間,也因某些優化可能會對業務上有些折中考慮,還會影響業務。
劍指主要矛盾
優先優化主要的性能瓶頸點
量化指標
在優化過程中,要時刻了解優化讓響應時間降低多少,提升多少吞吐量。
持續優化
高并發系統的業務邏輯都很復雜,出現性能問題也有多方面原因。因此,我們在做性能優化的時候要明確目標,比方說,支撐每秒1萬次請求的吞吐量下響應時間在10ms,那么我們就需要持續不斷地尋找性能瓶頸,制定優化方案,直到達到目標為止。
在以上四個原則的指引下,掌握常見性能問題的排查方式和優化手段,就一定能讓你在設計高并發系統時更加游刃有余。
3 性能的度量指標
一般度量性能的指標是系統接口的響應時間,需要收集一段時間的響應時間數據,然后依據統計方法計算特征值,這些特征值就能夠代表這段時間的性能情況。常見的特征值有以下幾類。
平均值
這段時間所有請求的響應時間數據和/總請求數。
在一定程度上反應這段時間的性能,但它敏感較差,若這段時間有少量慢請求,在平均值上并不能反應出來。
最大值
段時間內所有請求響應時間最長的值。
問題在于過于敏感。
分位值
有很多種,比如90分位、95分位、75分位。以90分位為例,我們把這段時間請求的響應時間從小到大排序,假如一共有100個請求,那么排在第90位的響應時間就是90分位值。分位值排除了偶發極慢請求對于數據的影響,能夠很好地反應這段時間的性能情況,分位值越大,對于慢請求的影響就越敏感。
分位值是最適合作為時間段內,響應時間統計值來使用的,在實際工作中也應用最多。
平均值也可以作為一個參考值。
通常使用吞吐量或者響應時間來度量并發和流量,使用吞吐量的情況會更多一些。這兩個指標是呈倒數關系:
響應時間1s時,吞吐量是每秒1次,響應時間縮短到10ms,那么吞吐量就上升到每秒100次。所以,一般我們度量性能時都會同時兼顧吞吐量和響應時間,比如我們設立性能優化的目標時通常會這樣表述:在每秒1萬次的請求量下,響應時間99分位值在10ms以下。
那么,響應時間究竟控制在多長時間比較合適呢?
從用戶使用體驗的角度來看,200ms是第一個分界點:接口的響應時間在200ms之內,用戶是感覺不到延遲的,就像是瞬時發生的一樣。而1s是另外一個分界點:接口的響應時間在1s之內時,雖然用戶可以感受到一些延遲,但卻是可以接受的,超過1s之后用戶就會有明顯等待的感覺,等待時間越長,用戶的使用體驗就越差。所以,健康系統的99分位值的響應時間通常需要控制在200ms之內,而不超過1s的請求占比要在99.99%以上。
現在你了解了性能的度量指標,那我們再來看一看,隨著并發的增長我們實現高性能的思路是怎樣的。
4 性能優化
假如說,你現在有一個系統,這個系統中處理核心只有一個,執行的任務的響應時間都在10ms,它的吞吐量是在每秒100次。那么我們如何來優化性能從而提高系統的并發能力呢?主要有兩種思路:一種是提高系統的處理核心數,另一種是減少單次任務的響應時間。
提高系統的處理核心數
提高系統的處理核心數就是增加系統的并行處理能力。
比如可以把系統的處理核心數增加為兩個,并且增加一個進程,讓這兩個進程跑在不同的核心上。這樣從理論上,你系統的吞吐量可以增加一倍。
這種情況下,吞吐量和響應時間就不是倒數關系了,而是:
吞吐量=并發進程數/響應時間
計算機領域的阿姆達爾定律(Amdahl’s law)是吉恩·阿姆達爾在1967年提出的。它描述了并發進程數與響應時間之間的關系,含義是在固定負載下,并行計算的加速比,也就是并行化之后效率提升情況,可以用下面公式來表示:
(Ws + Wp) / (Ws + Wp/s)
Ws表示任務中的串行計算量
Wp表示任務中的并行計算量
s表示并行進程數
可推出另外一個公式:
1/(1-p+p/s)
s還是表示并行進程數
p表示任務中并行部分的占比
當p為1時,也就是完全并行時,加速比與并行進程數相等;當p為0時,即完全串行時,加速比為1,也就是說完全無加速;當s趨近于無窮大的時候,加速比就等于1/(1-p),你可以看到它完全和p成正比。特別是,當p為1時,加速比趨近于無窮大。
我們似乎找到了解決問題的銀彈,無限制地增加處理核心數就能無限制地提升性能?
隨并發進程數的增加,并行的任務對于系統資源的爭搶也會愈發嚴重。在某一個臨界點上繼續增加并發進程數,反而會造成系統性能的下降,這就是性能測試中的拐點模型。
并發用戶數處于輕壓力區時,響應時間平穩,吞吐量和并發用戶數線性相關
并發用戶數處于重壓力區時,系統資源利用率到達極限,吞吐量開始有下降的趨勢,響應時間也會略有上升。這個時候,再對系統增加壓力,系統就進入拐點區,處于超負荷狀態,吞吐量下降,響應時間大幅度上升。
所以評估系統性能時通常需要做壓測,找到系統的“拐點”,從而知道系統的承載能力,也便于找到系統瓶頸,持續優化系統性能。
減少單次任務響應時間
首先看你的系統是CPU密集型還是IO密集型的,不同類型的系統性能優化方式不盡相同。
CPU密集型系統中,需要處理大量的CPU運算,那么選用更高效的算法或者減少運算次數就是這類系統重要的優化手段。比方說,如果系統的主要任務是計算Hash值,那么這時選用更高性能的Hash算法就可以大大提升系統的性能。發現這類問題的主要方式,是通過一些Profile工具來找到消耗CPU時間最多的方法或者模塊,比如Linux的perf、eBPF等。
IO密集型系統指的是系統的大部分操作是在等待IO完成:
磁盤IO
網絡IO
大部分都屬于IO密集型,比如數據庫系統、緩存系統、Web系統。這類系統的性能瓶頸可能出在系統內部,也可能是依賴的其他系統,而發現這類性能瓶頸的手段主要有兩類:
采用工具
Linux的工具集很豐富,完全可以滿足你的優化需要,比如網絡協議棧、網卡、磁盤、文件系統、內存,等等。這些工具的用法很多,你可以在排查問題的過程中逐漸積累。除此之外呢,一些開發語言還有針對語言特性的分析工具,比如說Java語言就有其專屬的內存分析工具。
監控來發現性能問題
在監控中我們可以對任務的每一個步驟做分時的統計,從而找到任務的哪一步消耗了更多的時間。
找到了系統瓶頸,如何優化呢?
如果是數據庫訪問慢,那么就要看是不是有鎖表的情況、是不是有全表掃描、索引加得是否合適、是否有JOIN操作、需不需要加緩存
如果是網絡的問題,就要看網絡的參數是否有優化的空間,抓包來看是否有大量的超時重傳,網卡是否有大量丟包等。
比如做廣告檢索遇到的問題,倒排索引存在Redis,每次都要請求Redis,但是并發時,Redis連接數太大,甚至打開文件數過大,后采用Redis連接池,Redis連接數得到控制,而且響應更快,后來隨著并發數的增大,連接池資源耗盡,而且Redis也有并發限制,數據傳輸導致大量占用帶寬,響應時間更久,因此,又使用了本地緩存,每次請求先請求本地緩存,找不到再請求Redis,緩存到本地,緩存更新時通過消息隊列來通知程序更新本地緩存,這樣節省了大量的和Redis之間的請求耗時和帶寬占用,性能有了數倍的提升。
總結
高并發:高性能(響應時間)、高可用(down機、故障、維護)、可擴展(應急擴容)
響應時間(平均值、最大值、分位值),響應為1s,吞吐量為每秒1次,響應縮短到10ms,吞吐量上升到每秒100次,從用戶體驗來說:200ms分界點,1s為另一個分界點,健康系統的99分位值的響應時間控制在200ms以內,不超過1s的請求占比要超過99.99%
高并發下的性能優化手段:
1.提高系統的處理核心數(吞吐量=核心數(并發進程數)/響應時間(s))
但并非無限增加核心數就可以增加吞吐量,隨著進程數增加,并行的任務對于資源的爭奪也增加,在某
個臨界點,進程增加導致系統的性能下降,這就是性能測試中的拐點模型,所以在評估系統性能時,需要做壓力測試,找到拐點
2.減少單次任務響應時間
cpu密集型:優化算法
io密集型:1.采用工具,linux的工具集
2.通過監控,對任務的每一個步驟做分時統計,從而找到任務中哪一步小號消耗了更多的時間
Redis 任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。