高併發系統設計三層面:系統性能篇
高併發系統設計三層面
高併發系統設計要點:
-
提高吞吐量(併發數):在拆分應用時,在水平方向拆應用,拆的層越多,吞吐量就會越高,但相應延時也會越高。同步架構:三層;異步架構:四層。在架構設計時,無狀態設計最重要。
-
響應延遲
性能優化層次有三個層面。
-
架構設計層次:如何拆分系統,如何使各個部分系統負載更加均衡,充分發揮硬件設施的性能優勢,減少系統內部開銷等。
-
算法邏輯層次:關注算法選擇是否高效、算法邏輯優化,空間時間優化任務並行處理,使用無鎖數據結構等;使用 ThreadLocal;採用壓縮算法壓縮數據,更復雜的邏輯減少數據傳輸。
-
代碼優化層次:關注代碼細節優化,代碼實現是否合理,是否創建了過多的對象,循環遍歷是否高效,cache 使用是否高效、合理,是否重用計算結果。
代碼優化層次
代碼優化層次包括:
-
循環遍歷是否合理高效,不要在循環裏調用 RPC 接口、查詢分佈式緩存、執行 SQL 等。要先調批量接口組裝好數據,再循環處理。
-
代碼邏輯避免生成過多的對象或無效對象:輸出 Log 的時候的 log 級別判斷,避免 new 無效對象。
-
ArrayList、HashMap 初始容量設置是否合理:擴容代價。
-
對數據對象是否合理重用,比如通過 RPC 查到的數據能複用則必須複用。
-
根據數據訪問特性選擇合適的數據結構,如果讀多寫少,考慮使用 CopyOnWriteArrayList(寫時拷貝副本)
-
拼接字符串的時候使用 String 相加還是使用 StringBuilder 進行 append(在 StringBuilder 的容量預分配前提下,StringBuilder 的性能比 String 相加性能高 15 倍左右)
-
是否正確初始化語句,有些全局共享的數據,餓漢式模式,在用戶訪問之前先初始化好。
列遍歷用 L1 Cache 列遍歷由於不滿足局部性原理,需要放到 L3 cache。行遍歷符合局部性原理,因此緩存命中率高,速度接近前者 2 倍。
CPU Cache 架構,按照以下順序速度越來越高:內存 ->L3->L2->L1。本質上內存使用一個大的一堆數組,二維數組在內存中按行排列,先存放 a【0】行,再存放 a【1】行
-
業務系統使用緩存降低響應時間提高性能,必須要提高緩存命中率。
-
很聚焦的高頻訪問,時效性要求不高很適合緩存提升性能,很聚焦的高頻訪問業務如 banner、廣告位時效性要求不是很高,比如更新了可以不用實時體現,很適合使用緩存提升性能。
-
如果對數據實時性要求很高,必須嚴格的時效性,需要慎重處理好更新緩存帶來的一致性問題。
-
時效性和緩存的衝突,比如商品服務對商品進行了緩存,由於更新緩存和更新商品不是同一個事務,則對數據實時性要求高的如交易,就只能直接從數據庫查詢商品信息。
-
當讀 <= 寫的時候 沒必要用緩存。、
-
當查詢條件數據量超過總數據庫總量的 30%,就不會用索引,直接用遍歷查詢。縮小範圍,讓條件覆蓋的數據量小一些。別查幾年的,查半個月的。
算法邏輯層優化:
-
用更高效的算法替換現有算法,而不改變其接口
-
增量式算法,複用之前的計算結果,比如一個報表服務,要從全量數據中生成
-
報表數據量很大,但每次增量的數據較少,則可以考慮只計算增量數據和之前計算結果合併,這樣處理的數據量就小很多。
-
併發和鎖的優化:讀多寫少:樂觀鎖;讀少寫多: 互斥鎖
-
系統時間是瓶頸:如緩存複用計算結果,降低時間開銷,因爲 CPU 時間比內存容量更加昂貴。
-
數據大小是瓶頸:網絡傳輸是瓶頸,使用系統時間換取換出的空間,使用 http 的 gzip 壓縮算法。app 的請求分類接口,使用版本號判斷哪些數據更新,是下載更新的數據。
-
並行執行:一段靠邏輯調用了多個 RPC 接口,而這些接口之間並沒有數據依賴,則可以考慮並行調用,降低響應時間。
-
異步執行:分析業務中的主次流程,把次要流程拆出來異步執行,更進一步拆分成單獨的模塊去執行,比如消息隊列,徹底和核心流程解耦,提高核心流程的穩定性以及降低響應時間。
架構設計優化:
-
系統微服務
-
無狀態化設計,動態水平彈性擴展
-
調用鏈路梳理,熱點數據儘量靠近用戶。
-
分佈式緩存,多級多類型緩存
-
提前拒絕,保證柔性可用
-
容量規劃
-
分佈分表,讀寫分離,數據分片。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/W5huymrp1FM8puXEO8QS0Q