常見性能優化策略

代碼層面優化

之因此把代碼放到第一位,是由於這一點最容易引發技術人員的忽視。實際上,第一步就應該是分析相關的代碼,找出相應的瓶頸,再來考慮具體的優化策略。有一些性能問題,徹底是因爲代碼寫的不合理,經過直接修改一下代碼就能解決問題的,好比for循環次數過多、做了不少無謂的條件判斷、相同邏輯重複屢次等。 html

Java代碼優化(長期更新)sql

經常使用技巧(僅列舉)

1.儘可能指定類、方法的final修飾符(方法內聯優化,去除方法調用的成本(如創建棧幀等)、爲其餘優化創建了良好的基礎)數據庫

2.儘可能重用對象(如StringBuilder/StringBuffer,單例模式)後端

3.儘量使用局部變量數組

4.及時關閉流緩存

5.儘可能採用懶加載的策略,即在須要的時候才建立(如懶漢式單例模式)性能優化

6.慎用異常,異常只能用於錯誤處理,不該該用來控制程序流程。服務器

7.若是能估計到待添加的內容長度,爲底層以數組方式實現的集合、工具類指定初始長度架構

8.儘可能避免隨意使用靜態變量(常駐內存)app

9.使用同步代碼塊替代同步方法

10.使用數據庫鏈接池和線程池(避免頻繁地打開和關閉鏈接;避免頻繁地建立和銷燬線程)

11.不捕獲Java類庫中定義的繼承自RuntimeException的運行時異常類

  • ArithmeticException能夠經過判斷除數是否爲空來規避
  • NullPointerException能夠經過判斷對象是否爲空來規避
  • IndexOutOfBoundsException能夠經過判斷數組/字符串長度來規避
  • ClassCastException能夠經過instanceof關鍵字來規避
  • ConcurrentModificationException可使用迭代器來規避

........

優秀的代碼來自每一點點小小的優化,關注每個細節,不只僅能提高程序運行效率,一樣能夠規避許多未知的問題。

數據庫層面優化

數據庫是最容易產生性能瓶頸的服務組件。

SQL調優

參考查詢性能優化建立高性能的索引

架構層面的調優

主從同步、讀寫分離、分庫分表及Sharding Sphere

(1)首先考慮讀寫分離,主數據庫處理事務性增刪改操做,從數據庫專門負責處理查詢操做,後臺進行主從同步。擴展了數據讀的能力,對於寫能力依然無法擴展。

(2)水平分區數據拆分,即將同一張表的數據拆分到不一樣的數據庫中,如經過UserID%8操做劃分。重要的原則是被拆分的數據儘量的平均拆分到後端的數據庫中。

(3)儘可能減小事務邊界(事務邊界,單個sql語句在後端數據庫上同時執行的數量)

若是每一條SQL語句都能帶有分庫分表鍵,經過分佈式服務層在對於SQL的解析後都能精確地將這條SQL語句推送到該數據所在的數據庫上執行;可是若是數據庫訪問不帶有分庫分表鍵,則會出現全表掃描,致使事務邊界的數量增大。會出現的問題:系統中鎖衝突的機率增長,系統難以擴展(整個平臺的數據庫鏈接能力是取決於後端單個數據庫的鏈接能力),總體性能下降(大數據量的聚合、排序、分組計算,會佔用較大的內存和CPU計算資源)。

買家在查看本身訂單的過程當中出現全表掃描,有違「儘可能減小事務邊界」這一原則

如何解決這類問題?異構索引表,拿空間換時間

採用異步機制將原表內的每一次建立或者更新,都換另外一個維度保存一份完整的數據表或者索引表,經過兩次帶分庫分表鍵的訪問代替了全表掃描。

鏈接池調優

這個時候就須要結合當前使用鏈接池的原理、具體的鏈接池監控數據和當前的業務量做一個綜合的判斷,經過反覆的幾回調試獲得最終的調優參數

緩存層面

緩存原理與實踐

異步操做層面

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

常見作法

一種作法,是額外開闢線程,這裏能夠採用額外開闢一個線程或者使用線程池的作法,在IO線程(處理請求響應)以外的線程來處理相應的任務,在IO線程中讓response先返回。

若是異步線程處理的任務設計的數據量很是巨大,那麼能夠引入阻塞隊列BlockingQueue做進一步的優化。具體作法是讓一批異步線程不斷地往阻塞隊列裏扔數據,而後額外起一個處理線程,循環批量從隊列裏拿預設大小的一批數據,來進行批處理(好比發一個批量的遠程服務請求),這樣進一步提升了性能。

另外一種作法,是使用消息隊列(MQ)中間件服務,MQ天生就是異步的。一些額外的任務,可能不須要我這個系統來處理,可是須要其餘系統來處理。這個時候能夠先把它封裝成一個消息,扔到消息隊列裏面,經過消息中間件的可靠性保證把消息投遞到關心它的系統,而後讓這個系統來作相應的處理。

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

NoSQL

看成DB用(非緩存場景)。

須要結合具體的業務場景,看這塊業務涉及的數據是否適合用NoSQL來存儲,對數據的操做方式是否適合用NoSQL的方式來操做,或者是否須要用到NoSQL的一些額外特性(好比原子加減等)。

若是業務數據不須要和其餘數據做關聯,不須要事務或者外鍵之類的支持,並且有可能寫入會異常頻繁,這個時候就比較適合用NoSQL(好比HBase)。

好比,公司內部有一個對exception作的監控系統,若是在應用系統發生嚴重故障的時候,可能會短期產生大量exception數據,這個時候若是選用MySQL,會形成MySQL的瞬間寫壓力飆升,容易致使MySQL服務器的性能急劇惡化以及主從同步延遲之類的問題,這種場景就比較適合用Hbase相似的NoSQL來存儲。

JVM調優

經過監控系統(如沒有現成的系統,本身作一個簡單的上報監控的系統也很容易)上對一些機器關鍵指標(gc time、gc count、各個分代的內存大小變化、機器的Load值與CPU使用率、JVM的線程數等)的監控報警,也能夠看gc log和jstat等命令的輸出,再結合線上JVM進程服務的一些關鍵接口的性能數據和請求體驗,基本上就能定位出當前的JVM是否有問題,以及是否須要調優。

JVM調優案例分析與實踐

相關文章
相關標籤/搜索