9大性能優化經驗總結,強烈建議收藏!

来源:https://www.cnblogs.com/mikechenshare/archive/2022/08/17/16594247.html
-Advertisement-
Play Games

性能優化屬於Java高級崗的必備技能,而且大廠特別喜歡考察,今天主要給大家介紹9種性能優化的方法@mikechen 1.代碼 之所以把代碼放到第一位,是因為這一點最容易引忽視,比如拿到一個性能優化的需求以後,言必稱緩存、非同步等。 實際上,第一步就應該是分析相關的代碼,找出相應的瓶頸,再來考慮具體的優 ...


性能優化屬於Java高級崗的必備技能,而且大廠特別喜歡考察,今天主要給大家介紹9種性能優化的方法@mikechen

1.代碼

之所以把代碼放到第一位,是因為這一點最容易引忽視,比如拿到一個性能優化的需求以後,言必稱緩存、非同步等。

實際上,第一步就應該是分析相關的代碼,找出相應的瓶頸,再來考慮具體的優化策略。

有一些性能問題,完全是由於代碼寫的不合理,通過直接修改一下代碼就能解決問題的,比如for迴圈次數過多、作了很多無謂的條件判斷、相同邏輯重覆多次等,這樣的優化成本是最低的。

 

2.資料庫

1.SQL優化

這裡以MySQL為例,最常見的方式是,由自帶的慢查詢日誌或者開源的慢查詢系統定位到具體的出問題的SQL,然後使用explain、profile等工具來逐步調優,最後經過測試達到效果後上線。

這裡舉幾個優化的例子:

1.查詢優化

對查詢進行優化,要儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。

2.避免null判斷

應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:

select id from t where num is null

3.避免全表掃描

應儘量避免在 where 子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描。

應儘量避免在 where 子句中使用 or 來連接條件,如果一個欄位有索引,一個欄位沒有索引,將導致引擎放棄使用索引而進行全表掃描。

in和 not in 也要慎用,否則會導致全表掃描,如:

select id from t where num in(1,2,3)

對於連續的數值,能用 between就不要用 in 了:

select id from t where num between 1 and 3

4.大數據量查詢

對於多張大數據量的表JOIN,要先分頁再JOIN,否則邏輯讀會很高。

5.合理使用索引

索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。

一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。

6.多使用數字型欄位

儘量使用數字型欄位,若只含數值信息的欄位儘量不要設計為字元型,這會降低查詢和連接的性能,並會增加存儲開銷。

這是因為引擎在處理查詢和連 接時會逐個比較字元串中每一個字元,而對於數字型而言只需要比較一次就夠了。

7.避免大數量

儘量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

8.避免大事務

儘量避免大事務操作,提高系統併發能力。

 

2.連接池調優

我們的應用為了實現資料庫連接的高效獲取、對資料庫連接的限流等目的,通常會採用連接池類的方案,即每一個應用節點都管理了一個到各個資料庫的連接池。

隨著業務訪問量或者數據量的增長,原有的連接池參數可能不能很好地滿足需求,這個時候就需要結合當前使用連接池的原理、具體的連接池監控數據和當前的業務量作一個綜合的判斷,通過反覆的幾次調試得到最終的調優參數。

更加全面深入的MySQL性能優化,請查看《MySQL慢查詢優化、索引優化、以及表等優化總結》。

 

3.架構層面

這一類調優包括讀寫分離、多從庫負載均衡、水平和垂直分庫分表等方面,一般需要的改動較大,但是頻率沒有SQL調優高,而且一般需要DBA來配合參與。

詳細的分庫分表、讀寫分離,請查看《資料庫分庫分表、讀寫分離的原理實現,使用場景

 

3.分散式緩存

緩存可以稱的上是性能優化的利器,緩存主要用來存放那些讀寫比很高、很少變化的數據。

什麼情況適合用緩存?考慮以下兩種場景:

  •  短時間內相同數據重覆查詢多次且數據更新不頻繁,這個時候可以選擇先從緩存查詢,查詢不到再從資料庫載入並回設到緩存的方式。此種場景較適合用單機緩存。
  •  高併發查詢熱點數據,後端資料庫不堪重負,可以用緩存來扛。

使用緩存需要註意的問題:

1.避免緩存失效

把頻繁修改的數據放入緩存,容易出現數據寫入緩存後,應用還來不及讀取緩存,數據就已經失效的情形,徒增系統負擔。

2.緩存熱點數據

緩存使用的記憶體資源非常寶貴,只能將最新訪問的數據緩存起來,而把歷史數據清理出緩存,即緩存資源應該留給20%的熱點數據。

 3.數據不一致性

一般會對緩存設置失效時間,超過失效時間,就要從資料庫重新載入。

因此應用要忍受一定時間的數據不一致,另一種策略是數據更新時立即更新緩存,不過這也會帶來更多的系統開銷和事務一致性的問題。

 4.緩存可用性

業務發展到一定階段時,緩存會承擔大部分數據訪問的壓力,資料庫已經習慣了有緩存的日子,所以當緩存伺服器崩潰時,資料庫會因為完全不能承受如此大的壓力而宕機,進而導致整個網站不可用,這種情況被稱作緩存雪崩,發生這種故障,甚至不能簡單地重啟緩存伺服器和資料庫伺服器來恢復網站訪問。

解決方式:

1)緩存熱備(當某台伺服器宕機時,將緩存訪問切換到熱備伺服器上;

2)緩存伺服器集群。

5. 緩存預熱

緩存中存放的是熱點數據,熱點數據是緩存系統用LRU對不斷訪問的數據篩選出來的,這個過程需要較長的時間。

新啟動的緩存系統沒有任何數據,此時系統的性能和資料庫負載都不太好。因此可以選擇在啟動緩存是就把熱點數據預載入好。

 6.緩存穿透

因為不恰當的業務或惡意攻擊,持續高併發地訪問某一個不存在的數據,如果緩存不保存該數據,就會有大量的請求壓力落在資料庫上。

簡單的解決方式是把請求的不存在的數據也放進緩存,其value是null。

如果還想全面瞭解緩存的5大難題,《如何解決Redis緩存雪崩、緩存穿透、緩存併發等5大難題》有更加深入全面的講解。

 

4.非同步化

針對某些客戶端的請求,在服務端可能需要針對這些請求做一些附屬的事情,這些事情其實用戶並不關心或者用戶不需要立即拿到這些事情的處理結果,這種情況就比較適合用非同步的方式處理這些事情。

非同步化的作用:

  •  縮短介面響應時間,使用戶的請求快速返回,用戶體驗更好。
  •  避免線程長時間處於運行狀態,這樣會引起服務線程池的可用線程長時間不夠用,進而引起線程池任務隊列長度增大,從而阻塞更多請求任務,使得更多請求得不到技術處理。
  •  線程長時間處於運行狀態,可能還會引起系統Load、CPU使用率、機器整體性能下降等一系列問題,甚至引發雪崩。非同步的思路可以在不增加機器數和CPU數的情況下,有效解決這個問題。

比如:使用消息隊列(MQ)中間件服務,MQ天生就是非同步的。

一些額外的任務,可能不需要我這個系統來處理,但是需要其他系統來處理,這個時候可以先把它封裝成一個消息,扔到消息隊列裡面,通過消息中間件的可靠性保證把消息投遞到關心它的系統,然後讓這個系統來做相應的處理。

再比如C端在完成一個提單動作以後,可能需要其它端做一系列的事情,但是這些事情的結果不會立刻對C端用戶產生影響,那麼就可以先把C端下單的請求響應先返回給用戶,返回之前往MQ中發一個消息即可,而且這些事情理應不是C端的負責範圍,所以這個時候用MQ的方式,來解決這個問題最合適。

 

5.Web前段

Web前端指網站業務邏輯之前的部分,包括:

  • 瀏覽器載入
  • 網站視圖模型
  • 圖片服務
  • CDN服務等

主要優化手段有優化瀏覽器訪問,使用反向代理,CDN等。

1.瀏覽器訪問優化

(1)減少http請求

HTTP協議是無狀態的應用層協議,意味著每次HTTP請求都需要簡歷通信鏈路,進行數據傳輸,而在伺服器端,每個HTTP都需要啟動獨立的線程去處理,這些通信和服務的開銷都很昂貴,減少HTTP請求的數目可有效提高訪問性能。

減少HTTP請求的主要手段是:

  •  合併CSS,以及壓縮CSS大小
  •  合併JavaScript,以及壓縮JS大小
  •  合併圖片

將瀏覽器一次訪問需要的JavaScript,CSS合併成一個文件,這樣瀏覽器就只需要一次請求。多張圖片合併成一張,如果每張圖片都有不同的超鏈接,可通過CSS偏移響應滑鼠點擊操作,構造不同的URL。

(2)使用瀏覽器緩存

對一個網站而言,CSS,JavaScript,Logo,圖標等這些靜態資源文件更新的頻率都比較低,而這些文件又幾乎是每次HTTP請求都需要的,如果將這些文件緩存在瀏覽器中,可以極好地改善性能。通過設置HTTP頭中Cache-Control和Expires屬性,可設定瀏覽器緩存,緩存時間可以是數天甚至是幾個月。有時候,靜態資源文件變化需要及時應用到客戶端瀏覽器,這種情況可以通過改變文件名實現,比如一般會在JavaScript後面加上一個版本號,使瀏覽器刷新修改的文件。

(3)啟用壓縮

在伺服器端對文件進行壓縮,在瀏覽器端對文件解壓縮,可有效較少通信傳輸的數據量。文本文件的壓縮效率科大80%以上。

(4)CSS放在頁面最上面,JavaScript放在頁面最下麵

瀏覽器會在下載完全部CSS之後對整個頁面進行渲染,因此最好的做法是將CSS放在頁面最上面,讓瀏覽器儘快下載CSS。JS則想法,瀏覽器在載入JS後立即執行,有可能會阻塞整個頁面,造成頁面顯示緩慢,因此JS最好放在頁面最下麵。

(5)減少Cookie傳輸

一方面,Cookie包含在每次請求和響應中,太大的Cookie會嚴重影響數據傳輸,因此哪些數據需要寫入Cookie需要慎重考慮,儘量減少Cookie中傳輸的數據量。另一方面,對於某些靜態資源的訪問,如CSS,JS等,發送Cookie沒有意義,可以考慮靜態資源使用獨立功能變數名稱訪問,避免請求靜態資源時發送Cookie,減少Cookie傳輸的次數。

2.CDN加速

CDN(Content Distribute Network,記憶體分髮網絡)的本質上仍然是一個緩存,而且將數據緩存在離用戶最近的地方,是用戶以最快速度獲取數據,即所謂網路訪問第一跳。

CDN一般緩存的是靜態資源,如圖片,文件,CSS,Script腳本,靜態網頁等,但是這些文件訪問頻率很高,將其緩存在CDN可極大改善網頁的打開速度。

3.反向代理

傳統代理伺服器位於瀏覽器一側,代理瀏覽器將HTTP請求發送到互聯網上,而反向代理伺服器位於網站機房一側,代理網站Web伺服器接收HTTP請求。

和傳統代理伺服器可以保護瀏覽器安全一樣,反向代理伺服器也具有保護網站安全的作用,來自互聯網的訪問請求必須經過代理伺服器,相當於在Web伺服器和可能的網路攻擊之間建立了一個屏障。

除了安全功能,代理伺服器也可以通過配置緩存功能加速Web請求,當用戶第一次訪問靜態內容的時候,靜態內容就被緩存在反向代理伺服器上,這樣當其他用戶訪問該靜態內容的時候,就可以直接從反向代理伺服器返回,加速Web請求響應速度,減輕伺服器負載要。

 

6.服務化

做服務化最基礎的是按業務做服務拆分,避免跨業務間的互相影響,數據和服務同時拆分。同一個業務內部我們還按計算密集型/IO密集型的服務拆分、C端/B端服務拆分、核心/非核心服務拆分、高頻服務單獨部署等原則做拆分。

 

7.硬體升級

硬體問題對性能的影響不容忽視。

舉一個例子:一個DB集群經常有慢SQL報警,業務排查下來發現SQL都很簡單,該做的索引優化也都做了,後來DBA同學幫忙定位到問題是硬體過舊導致,將機械硬碟升級成固態硬碟之後報警立馬消失了,效果立竿見影!

 

8.搜索引擎

複雜查詢以及一些聚合計算不適合在資料庫中做,可以利用搜索引擎來實現,另外搜索引擎還可以幫我們很好的解決跨庫、跨數據源檢索的場景。

 

9.產品邏輯優化

業務邏輯優化經常會容易被忽略,但效果卻往往比資料庫性能優化JVM調優之類的來的更明顯。

舉一個例子,12306春運搶火車票的場景,由於訪問的人多,用戶點擊“查票”之後系統會非常卡,進度條非常慢,作為用戶,我們會習慣性的再去點“查票”,可能會連續點個好幾次。

假設平均一個用戶點5次,則後端系統負載就增加了5倍!而其中80%的請求是重覆請求。

這個時候我們可以通過產品邏輯的方式來優化,比如,在用戶點擊查詢之後將“按鈕置灰”,或者通過JS控制xx秒只能只能提交一次請求等,有效的攔截了80%的無效流量。

 

以上

作者簡介

陳睿|mikechen,10年+大廠架構經驗,《BAT架構技術500期》系列文章作者,分享十餘年BAT架構經驗以及面試心得!

閱讀mikechen的互聯網架構更多技術文章合集

Java併發|JVM|MySQL|Spring|Redis|分散式|高併發|架構師

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 新建項目 點擊+號 進入創建場景,選擇對應的選項和自己的AppID 為了不見黃色警告熱重載,可以選擇關閉。 在project.config.json項目的配置文件的setting配置添加如下: "checkSiteMap":false 2. 配置首頁 2.1 新建項目與梳理項目結構 點擊app ...
  • 為了保護用戶隱私,大多數應用只會在前臺運行時獲取用戶位置,當應用在後臺運行時,定位功能會被禁止。這就導致APP在後臺或者鎖屏時無法正常記錄GPS軌跡,這對打車、共用出行、跑步等需要實時記錄用戶軌跡的應用影響非常大,甚至影響了應用核心功能的使用體驗。那對於這些應用的開發者來說,如何在用戶主動授權位置信 ...
  • 今天在學習如何使用npm安裝包的時候,在使用 npm install xxx -g 安裝全局包時, 發現安裝的包無法使用。而安裝時cmd卻沒有報錯,這令我很疑惑,這應該是安裝成功了但卻不能使用。 如下圖所示 在查詢了資料後,使用了 npm root -g 命令,獲得了全局包的安裝路徑,打開後發現該路 ...
  • 使用$parent訪問父級組件實例 點擊打開視頻講解更詳細 和 $root 類似,$parent property 可以用來從一個子組件訪問父組件的實例。它提供了一種機會,可以在後期隨時觸達父級組件,以替代將數據以 prop 的方式傳入子組件的方式。 註意:在絕大多數情況下,觸達父級組件會使得你的應 ...
  • 前端周刊:2022-13 期 前端開發 Vue3 文檔更新 更新後的 Vue3 文檔分別提供了選項式和組合式兩個版本,內容豐富程度和細緻程度也有很大提升,推薦大家重讀一遍。 前端請求併發控制 所有請求都在一個數組中,以限定的併發數將請求發完 前端 API 請求的各種騷操作 併發控制 / 節流控制 / ...
  • 處理邊界情況之使用$root訪問根實例 點擊打開視頻教程 在每個 new Vue 實例的子組件中,其根實例可以通過 $root property 進行訪問。 例如,在這個根實例中: src\main.js import Vue from 'vue' import App from './App.vu ...
  • 本文是深入淺出 ahooks 源碼系列文章的第七篇,該系列已整理成文檔-地址。覺得還不錯,給個 star 支持一下哈,Thanks。 今天我們來聊聊定時器。 useInterval 和 useTimeout 看名稱,我們就能大概知道,它們的功能對應的是 setInterval 和 setTimeou ...
  • 行為型模式(Behavioral Pattern)是指對在不同對象之間劃分責任和演算法進行抽象化的設計模式,它不僅關註類和對象的結構,而且重點關註他們之間的相互作用。 對於一個系統來說,對象不是孤立運行的,對象之間可以通過相互通信和協作完成某些複雜的功能,對象之間是相互影響的。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...