接口的性能優化(前端、后端、數據庫)
主要通過三方面進行優化
- 前端
- 后端
- 數據庫
前端優化
接口拆分
不要搞一個大而全的接口,要區分核心與非核心的接口,不然核心接口就會被非核心接口拖累
或者一個接口中大部分返回都很快,但是被其中某個邏輯拖累,導致整個接口都很慢,這時候就可以把這個慢的邏輯抽出來,單獨做一個接口
什么是核心呢?比如你是視頻或者直播網站,那么你的視頻、直播的內容就是核心,要先調用視頻、直播的接口,保證核心內容能夠正常加載,然后再加載評論、禮物等接口。
當然接口的拆分也不宜過多,因為每次接口的請求與斷開也都會消耗資源。
按需加載
如果你的接口是返回一篇文章,如果文章很長,則不要直接返回全部內容(尤其設計多圖片、視頻),可根據用戶閱讀進度進行逐步加載。
如果是返回列表,則不要全部返回,而要分頁顯示。
及時反饋用戶狀態
有些接口返回較慢,用戶觸發后(比如點擊按鈕),可能無法立即返回結果。
這時候如果等待接口返回結果后再給用戶反饋,那么用戶在等待的過程中就會以為自己的操作沒有生效,這時候不僅用戶體驗不好,同時用戶還可能會重復點擊,造成多次接口訪問,同時也會消耗資源。
為避免這種情況,要求用戶觸發某個動作時,要立刻給用戶一個反饋,比如顯示“加載中,請等待。。”等字樣。
當然前端也可以通過其他方式來限制用戶重復點擊的問題,比如設置過期時間,加鎖等方式
接口并行訪問
如果接口之前沒有依賴關系,可并行訪問,加快訪問速度
靜態資源CDN
靜態資源包括圖片、視頻等媒體問題,同時也包括js、css、html等一些文本文件。相同的是這些文件都是靜態,也就是短期內不會變化的問題。
這些文件就非常適合通過CDN進行加速分發
靜態資源緩存
與上述原因相同,因為是靜態資源,所以也可以緩存在本地
后端優化
限流、熔斷與降級
限流是針對服務請求數量的一種自我保護機制,當請求數量超出服務的處理能力時,會自動丟棄新來的請求。
熔斷這一概念來源于電子工程中的斷路器(Circuit Breaker)。在互聯網系統中,當下游服務因訪問壓力過大而響應變慢或失敗,上游服務為了保護系統整體的可用性,可以暫時切斷對下游服務的調用。
降級是將某些不重要的業務關閉,保證核心功能可用。降級的思想是丟車保帥。
防止重復點擊
防止多次重復點擊,每次接口調用,都會消耗后端資源。
可通過加鎖的方式實現
使用多線程
涉及多個對象的操作,尤其是列表循環的操作,可以引入多線程,把之前的串行操作改為并行,大大提高效率
如果涉及到多個線程之前的等待,可是使用CountDownLatch、CyclicBarrier和Semaphore,可參考https://blog.csdn.net/CrankZ/article/details/83781380
異步
一些與主流程不相關的或者耗時較長的處理,可以改為異步,比如發送短信、郵件等
異步的方式有很多種,比如直接新建線程
或者引入第三方MQ
等
緩存
根據我的經驗,IO操作(包括與數據庫的交互和網絡接口的交互)都是占用耗時的大頭。所以如果能適當針對這些IO操作加上緩存,將會大大的提高性能。
緩存主要分2類,本地緩存(Caffeine為代表)、遠程緩存(Redis為代表),可針對不同的場景進行使用。
當然也可以結合兩者,組成二級緩存,這里可以使用阿里開源的組件 https://github.com/alibaba/jetcache
緩存相關內容可參考我的另一篇文章 https://blog.csdn.net/CrankZ/article/details/80537115
本地緩存可參考我的另一篇文章 https://blog.csdn.net/CrankZ/article/details/90344348
數據庫連接池
數據庫的每次連接與關閉,都會消耗資源,如果每次都這樣重新建立并銷毀連接,這樣會性能低下。
所以數據庫連接池的建立多個數據庫連接,并將這些連接組成一個連接池,由應用程序動態地對池中的連接進行申請、使用和釋放。
數據庫連接池可參考 https://blog.csdn.net/CrankZ/article/details/82874158
JVM優化
啟動的內存大小、選擇合適GC等
組件升級
升級底層組件,比如升級到Java21,在Java21中可以啟用虛擬線程、使用新增的GC等
數據庫優化
數據庫選擇
首先要針對不同的數據,選擇合適的數據庫
常規關系型數據除了常見的MySQL,還可以選擇PostgreSQL,TiDB等
非關系型數據,比如大文本,JSON等,可以考慮MongoDB
如果涉及搜索的,可以使用Elasticsearch或者ClickHouse等
圖數據庫,比選擇Neo4j等
下面以MySQL為代表,講一些關系型數據庫的優化
讀寫分離
增加從節點,從節點專注讀請求,主節點專注處理寫請求。
主庫與從庫的結構完全一樣,一個主庫可以有多個從庫
可參考我另一篇文章 https://blog.csdn.net/CrankZ/article/details/84679742
分庫分表
當單庫單表無法滿足需求時,可考慮分庫分表。
這里不做贅述,可參考我另一篇文章 https://blog.csdn.net/CrankZ/article/details/84679742
歸檔歷史數據,降低單表規模
MySQL并不適合存儲大數據量,如果不對數據進行歸檔,數據庫會持續膨脹,從而降低查詢和寫入的性能。為了滿足大數據量的讀寫需求,需要定期對數據庫進行歸檔。
在進行數據庫設計時,需要事先考慮到對數據歸檔的需求。
如果有需要,可以考慮專門的數據倉庫Hive或者HBase等
索引優化
避免索引失效
,盡量保證每次查詢都命中索引
可參考我另一篇文章 https://blog.csdn.net/CrankZ/article/details/80468760
參考
https://juejin.cn/post/7287420810318299190