效能優化有感

ingxx發表於2020-04-25

效能優化有感

效能優化是個枯燥,卻又有趣的過程
效能優化我大致分為幾個方面

  • 程式碼優化
  • 執行緒優化、非同步
  • JVM優化
  • 資料庫優化
  • 快取優化
  • 架構優化

下面來展開談談感悟,也可以參考美團技術團隊常見效能優化

程式碼優化

程式碼是跟我們接觸最多的東西,程式碼優化主要有

  1. 程式碼結構優化,可以方便日後擴充套件和程式碼標準化
    • 是否可以進行抽象避免冗餘程式碼
    • 是否可以利用設計模式
    • 程式碼是否遵循阿里巴巴Java開發手冊

這裡可以採用阿里巴巴Java開發規範外掛

  1. 程式碼是否有多重迴圈,無效的查詢等
    • 多重迴圈可以根據資料量採用HashMap進行查詢,屬於利用空間換取時間
    • 無效的查詢等可以進行刪除
      這裡推薦Findbugs

執行緒優化

執行緒優化是一個複雜的過程,多執行緒如何運用,如何避免死鎖、飢餓、活鎖等問題

  1. 執行緒使用的地方

    • 在查詢中可以運用到多執行緒,把序列化操作變化為並行化操作
    • I/O阻塞的操作,最經典的莫過於BIO
    • 計算量大的操作,使用多執行緒可以更好的運用CPU的運算能力
  2. 執行緒池
    需要了解執行緒池的狀態,執行緒池的引數,以及內部原理,並選擇合適的執行緒池
    這裡推薦一篇文章Java執行緒池實現原理及其在美團業務中的實踐 再次感謝美團技術團隊

    • 執行緒池分為
      • newCachedThreadPool
      • newFixedThreadPool
      • newSingleThreadExecutor
      • newScheduleThreadPool
      • forkjoinPool
        注意:這裡不建議使用Executors來建立執行緒池,方式OOM等問題,參考阿里巴巴開發規範,建議使用new ThreadPoolExecutor()
  3. 非同步
    非同步建議採用MQ,使用範圍例如insert、update操作,可以丟到MQ,這裡要注意MQ訊息丟失問題,同時MQ也可以實現延遲佇列,例如30分鐘關閉訂單,採用Job的方式並不是一個好的解決方案,可以採用MQ延時佇列實現,這裡推薦rocketmq(阿里巴巴牛逼)

  4. 併發容器的選擇
    concurrenthashmap和synchronizedmap效能差距很大,建議選擇合適的併發容器

JVM優化

JVM優化這裡本人也不是特別的熟練,只是講一些自己所知道的

  1. 無日誌不優化
    在沒有日誌的情況下,該怎麼優化,如何優化,哪些方面需要優化,這裡都是未知的,所以需要日誌才能進行優化
  2. 工具
    優化要有趁手的工具,好在JDK本身就為我們提供了不少,在JDK的bin目錄下有一堆自帶的工具,這裡介紹幾個我熟悉且用過的
    • jps:檢視當前機器上的java程式
    • jcmd:跟jps差不多但是能看到啟動命令
    • jstat:檢視JVM資訊,例如GC資訊
    • jinfo:檢視JVM引數
    • jmap:JVM在記憶體中的情況,可以匯出Dump
    • jstack:棧資訊,可以用來檢視死鎖等
    • jconsole:一個視覺化工具
    • jvisualvm:也是一個視覺化工具比jconsole功能強一些,但是都有侷限性,在伺服器上無法使用
    • eclipse memory analyer:分析dump檔案
  3. 引數優化
    使用上面的工具對伺服器進行監控,可以根據資訊適當的調整堆大小,GC收集器等。建議開啟-XX:+HeapDumpOnOutOfMemoryError

資料庫優化

資料庫是優化中重要的一環,具體優化方法如下

  1. SQL優化:是否可以去掉不必要的查詢,使用explain對sql進行分析,避免回表等
  2. 分庫分表:一臺資料庫可能存在效能瓶頸,可以採用分庫分表的方式,拆分主要採用冷熱資料分離、日期分割、HASH取模等。
  3. 讀寫分離:對資料的修改可以操作主庫,對資料的查詢可以操作從庫,進行讀寫分離
    分庫分表以及讀寫分離後可能會出現分散式事務、讀寫分離操作的複雜性等問題這裡需要引入中介軟體例如:MyCat sharding jdbc

快取優化

快取是個優化的好辦法但是也有弊端

  1. 快取分類
    • JVM快取:concurrenthashmap、guava快取
    • Redis等NoSQL資料庫
  2. 快取拆分
    可以在程式碼中對介面進行拆分,可以快取的和不可以快取的寫成多個方法,對可以快取的進行快取
  3. 快取帶來的弊端
    快取並不是越多越好,快取給系統帶來了複雜性,例如:何時新增快取、何時刪除快取、快取雪崩、快取擊穿、快取穿透、快取預熱、Redis叢集如何實現、Redis哨兵、Redis腦裂等問題

架構優化

架構優化其實就程式設計師來說能做的並不是很多

  1. 限流:GateWay進行限流,限流方法有滑動視窗、漏桶、令牌桶演算法,這裡建議採用合適的方法進行限流防止應用崩潰
  2. 熔斷:可以採用hystrix防止服務雪崩
  3. CDN優化:對靜態資源採用CDN可以提交響應速率
  4. DNS優化:這個暫時不熟可以交給運維處理
  5. 服務擴容:可以採用K8S和Docker的技術對服務進行動態擴容,這裡也是運維實現

測試

優化了這麼多,體現當然是壓力測試,這裡因為不熟悉效能指標,單機TPS部分介面可以達到800+ RT在300ms以內,希望大家提供一個單機效能標準,以上採用的是LoadRuner測試的結果

洋洋灑灑寫了這麼多,主要的還是平時的積累以及思考,也希望您對內容進行補充。

相關文章