互聯(lián)網(wǎng)高并發(fā)設(shè)計(jì)的手段:架構(gòu)、算法、代碼
性能優(yōu)化目標(biāo)
1、縮短響應(yīng)時(shí)間
2、提高并發(fā)數(shù)(增加吞吐量)
3、讓系統(tǒng)處于合理狀態(tài)
圖片
性能優(yōu)化手段
1、空間換時(shí)間
系統(tǒng)時(shí)間是瓶頸: 緩存復(fù)用計(jì)算結(jié)果,降低時(shí)間開銷,因?yàn)閏pu時(shí)間較內(nèi)存容量更加昂貴。
2、時(shí)間換空間
- 數(shù)據(jù)大小是瓶頸
- 網(wǎng)絡(luò)傳輸是瓶頸,使用系統(tǒng)時(shí)間換取傳輸?shù)目臻g,使用HTTP的gzip壓縮算法
- app的請(qǐng)求分類接口,使用版本號(hào)判斷哪些數(shù)據(jù)更新,只下載更新的數(shù)據(jù)
3、找到系統(tǒng)瓶頸
- 分析系統(tǒng)的業(yè)務(wù)流程,找到關(guān)鍵路徑并分解優(yōu)化
- 調(diào)用了多少RPC接口,載入多少數(shù)據(jù),是用什么算法,非核心流程是否異步化。
性能優(yōu)化層次
1、架構(gòu)設(shè)計(jì)層次
如何拆分系統(tǒng) 如何使用部分系統(tǒng)整體負(fù)載更加均衡 充分發(fā)揮硬件設(shè)施性能優(yōu)勢(shì) 減少系統(tǒng)內(nèi)部開銷等
2、算法邏輯層次
關(guān)注算法選擇是否高效,算法邏輯優(yōu)化,空間時(shí)間優(yōu)化任務(wù)執(zhí)行吃力,使用無(wú)鎖數(shù)據(jù)結(jié)構(gòu)。
空間換時(shí)間:ThreadLocal
時(shí)間換空間:采用壓縮算法壓縮數(shù)據(jù),更復(fù)雜的邏輯減少數(shù)據(jù)傳輸。
3、代碼優(yōu)化層次
關(guān)注代碼細(xì)節(jié)優(yōu)化,代碼實(shí)現(xiàn)是否合理,是否創(chuàng)建了過(guò)多的對(duì)象,循環(huán)遍歷是否高效,cache使用是否合理
優(yōu)化層次:從整理到細(xì)節(jié),從全局角度到局部視角。
代碼優(yōu)化層次(1)
- 循環(huán)遍歷是否合理高效,不要在循環(huán)里調(diào)RPC接口,傳輸分布式緩存 執(zhí)行SQL等
- 先調(diào)用批量接口組裝好數(shù)據(jù),再循環(huán)處理
- 代碼邏輯避免生成過(guò)多的對(duì)象和無(wú)效對(duì)象
- 輸出Log時(shí)候的log級(jí)別判斷 避免new無(wú)效對(duì)象
- ArrayList、HashMap初始容量設(shè)置是否合理
- 對(duì)數(shù)據(jù)對(duì)象是否合理重用 比如RPC查到的數(shù)據(jù)能復(fù)用則必須復(fù)用,根據(jù)數(shù)據(jù)訪問(wèn)特性選擇合適數(shù)據(jù)結(jié)構(gòu),比如讀多寫少考慮 CopyOrWriteArrayList(寫時(shí)copy副本),會(huì)否正確初始化數(shù)據(jù),有些全局共享的數(shù)據(jù),餓漢式模式,在用戶使用之前先初始化好。
代碼優(yōu)化層次(2)
- CPU Cache結(jié) 構(gòu)
- 速度越來(lái)越高:內(nèi)存 - >L3->L2->L1多級(jí)緩存
- 本質(zhì)上內(nèi)存是一個(gè)大的一維數(shù)組,二維數(shù)組在內(nèi)存中按行排列,先存放a[0]行,再存放a[1]行
- 第一種遍歷方式,是行遍歷,先遍歷完一行再遍歷第二行,符合局部性原理Cache Hit (緩存命中率高)
- 第二種遍歷方式,是列遍歷,遍歷完第一列遍歷第二列,由于下一列和 上 一 列的數(shù)組元素在內(nèi)存中并不是連續(xù)的,很可能導(dǎo)致Cache Miss ( 緩 存 未 命 中 ) , CPU 需要去內(nèi)存載入數(shù)據(jù),速度較CPU L1Cache的速度降低 了很多(主存100ns,L1 cache 0.5ns)
圖片
數(shù)據(jù)優(yōu)化層次
select count(*)from table where add time<"2017- 11-0623:59:59" and status=0 add count in(1,2) ORDER BY id ASC;
代碼邏輯要適應(yīng)數(shù)據(jù)變化的場(chǎng)景
圖片
圖片
圖片
算法優(yōu)化邏輯層次
●用更高效的算法替換現(xiàn)有算法,而不改變其接口
● 增量式算法,復(fù)用之前的計(jì)算結(jié)果,比如一個(gè)報(bào)表服務(wù),要從全量數(shù)據(jù)中生成報(bào)表數(shù)據(jù)量很大,但是每次增量的數(shù)據(jù)較少,則可以考慮只計(jì)算增量數(shù)據(jù)和之前計(jì)算結(jié)果合并,這樣處理的數(shù)據(jù)量就小很多
● 并發(fā)和鎖的優(yōu)化,讀多寫少的業(yè)務(wù)場(chǎng)景下,基于CAS的LockFree比mutex 性能更好
● 當(dāng)系統(tǒng)時(shí)間是瓶頸,采取空間換時(shí)間邏輯算法,分配更多空間節(jié)省系統(tǒng)時(shí)間
● 緩存復(fù)用計(jì)算結(jié)果,降低時(shí)間開銷, CPU時(shí)間較內(nèi)存容量更加昂貴
● 當(dāng)系統(tǒng)空間容量是瓶頸,采取時(shí)間換空間算法策略
● 網(wǎng)絡(luò)傳輸是瓶頸,使用系統(tǒng)時(shí)間換取空間的壓縮, HTTP的gzip 壓縮算法
● APP的請(qǐng)求分類接口,使用版本號(hào)判斷哪些數(shù)據(jù)更新,只下載更新的數(shù)據(jù),使用更多的代碼邏輯處理更細(xì)粒 度的數(shù)據(jù)
● 并行執(zhí)行,比如一段邏輯調(diào)用了多個(gè)RPC接口,而這些接口之間并沒(méi)有數(shù)據(jù)依賴,則可以考慮并行調(diào)用,降低響 應(yīng)時(shí)間
● 異步執(zhí)行,分析業(yè)務(wù)流程中的主次流程,把次要流程拆分出來(lái)異步執(zhí)行,更進(jìn)一步可以拆分到單獨(dú)的模塊去執(zhí)行, 比如使用消息隊(duì)列,徹底和核心流程解耦,提高核心流程的穩(wěn)定性以及降低響應(yīng)時(shí)間
架構(gòu)層次優(yōu)化
● 系統(tǒng)微服務(wù)化
● 無(wú)狀態(tài)化設(shè)計(jì),動(dòng)態(tài)水平彈性擴(kuò)展
● 調(diào)用鏈路梳理,熱點(diǎn)數(shù)據(jù)盡量靠近用戶
● 分布式Cache 、 多級(jí)多類型緩存
● 提前拒絕,保證柔性可用
● 容量規(guī)劃
● 分庫(kù)分表,讀寫分離,數(shù)據(jù)分片
案例:
圖片
Feed流系統(tǒng)分級(jí)緩存
讀多寫少、冷熱數(shù)據(jù)明顯,熱點(diǎn)數(shù)據(jù)緩存到調(diào)用鏈路更靠近用戶的地方
● L1緩存容量小負(fù)責(zé)抗最熱點(diǎn)的數(shù)據(jù), L2緩存考慮目標(biāo)是容量,緩存更大范圍的數(shù)據(jù)(一般用戶的timeline), 高熱點(diǎn),數(shù)據(jù)單獨(dú)緩存,比如設(shè)置白名單,大V 的用戶數(shù)據(jù)放在L1緩存
● feed(關(guān)注的feed 、topic 的feed,一些運(yùn)營(yíng)的feed),前幾頁(yè)的訪問(wèn)比例,前三頁(yè)占了90%+,針對(duì)這種業(yè)務(wù)特性,把 前面幾頁(yè)數(shù)據(jù)作為熱點(diǎn)數(shù)據(jù)提到L1 cache
Feed系統(tǒng)消息發(fā)布
寫擴(kuò)散 (PUSH)
● 推送策略:拆分?jǐn)?shù)據(jù)并行推,活躍用戶先推,非活躍用戶慢慢推
● 有 1w個(gè)用戶關(guān)注,發(fā)了一個(gè)feed,拆分成100份,每份100個(gè)并行推
● 1w個(gè)用戶里活躍的可能有2000個(gè),活躍用戶先推,非活躍用戶慢慢推,保證活躍用戶體驗(yàn),非活躍用戶推 了很大概率也不看
讀擴(kuò)散(PULL)
圖片
Feed系統(tǒng)存儲(chǔ)選型