數據庫連接池優化


一、數據庫瓶頸解決方案

  在大流量時,數據庫會成為系統瓶頸,其總體的解決方案如下:

    1、項目架構使用緩存,90%請求攔截上游服務器 ———— 讀操作

    2、數據歸檔處理 (把一些用戶不訪問的數據直接歸檔處理,緩解數據庫壓力)--使用master ,slave架構

    3、停機擴容

  影響數據庫性能因數:

    1、服務器硬件

    2、操作系統

    3、存儲引擎

    4、數據庫表結構(冗余設計)

    5、SQL 語句

    6、磁盤 IO

    7、網卡流量

    8、慢查詢

  總結來看:

    1、低效 SQL 語句

    2、並發 cpu 的問題(SQL 並不支持多核心 cpu 並發模式執行,一個 SQL 語句只能在一個 cpu 進行執行)

    3、連接數: max-connections

    4、大表(數據多,字段多)

    5、大事務

    6、超高 cpu 使用率

  其中大表、大事務、低效SQL都是屬於項目設計和開發時需要注意的,而連接數是需要進行提前設置好的。

二、連接數調優

  首先從數據庫連接池選型上,目前比較主流的有HikariCP 和阿里的Druid,HikariCP讀性能很好,但是寫性能一般,阿里的Druid就比較均衡,無論讀寫都很好,因此使用了阿里的Druid。

  相關的配置項如下所示,都加了注釋。

spring:
  application:
    name: sugo-seckill-web
  datasource:
    #url: jdbc:mysql://127.0.0.1:3306/shop?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    url: jdbc:mysql://172.20.10.14:3306/shop?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&connectionTimeout=3000&socketTimeout=1200
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    druid:
      #初始化線程數
      initial-size: 1
      # 最小線程數
      min-idle: 5
      # 最大線程數
      max-active: 10
      # 獲取連接最大等待時間
      max-wait: 1200
      # 銷毀線程的間隔時間
      time-between-eviction-runs-millis: 600000
      # 配置一個連接在池中最大空閑時間,單位是毫秒
      min-evictable-idle-time-millis: 300000
      # 設置從連接池獲取連接時是否檢查連接有效性,true時,每次都檢查;false時,不檢查
      test-on-borrow: true
      #設置往連接池歸還連接時是否檢查連接有效性,true時,每次都檢查;false時,不檢查
      test-on-return: true
      # 設置從連接池獲取連接時是否檢查連接有效性,true時,如果連接空閑時間超過minEvictableIdleTimeMillis進行檢查,否則不檢查;false時,不檢查
      test-while-idle: true
      # 檢驗連接是否有效的查詢語句。如果數據庫Driver支持ping()方法,則優先使用ping()方法進行檢查,否則使用validationQuery查詢進行檢查。(Oracle jdbc Driver目前不支持ping方法)
      validation-query: select 1 from dual
      # 是否長鏈接
      keep-alive: true
      # 是否刪除異常連接
      remove-abandoned: true
      # 異常連接的判斷條件(80毫秒沒有使用的連接,防止線程阻塞)
      remove-abandoned-timeout: 80
      log-abandoned: true
      #打開PSCache,並且指定每個連接上PSCache的大小,Oracle等支持游標的數據庫,打開此開關,會以數量級提升性能,具體查閱PSCache相關資料
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      # 配置間隔多久啟動一次DestroyThread,對連接池內的連接才進行一次檢測,單位是毫秒。
      #檢測時:
      #1.如果連接空閑並且超過minIdle以外的連接,如果空閑時間超過minEvictableIdleTimeMillis設置的值則直接物理關閉。
      #2.在minIdle以內的不處理。

三、連接池參數優化

  其實數據庫連接池優化主要就是優化最大連接數、獲取連接等待時間、連接超時時間和會話超時時間四項,其他的就直接按照上述的參數配置即可,基本上不需要調整。

(一)壓測

  使用jmeter進行壓測

  1、創建一個線程組--數據庫連接池測試

  2、添加--配置原件--JDBC Connection Configuration 

    需要配置連接池名字、最大連接數、最大等待時間等,還需要配置驗證sql、數據庫信息

      

 

     然后還需要添加一下驅動包,在測試計划中添加jar包即可。

  3、添加--取樣器--JDBC Request,需要添加連接池名字(mysql),sql語句,處理方式(這里選擇預處理),sql的參數和參數類型

      

 

    4、添加--監聽器--結果樹

    5、添加--監聽器--聚合報告

    6、添加--監聽器--TPS

    7、添加--監聽器--RT  

(二)參數調整

  1、max-active : 最大連接數

    在數據庫連接池優化時,最重要的就是最大連接數的優化,太小太大都會影響性能,那么如何設置最大連接數,就成為優化的關鍵。

    試驗: max-active = 10 , TPS 測試的結果如下所示:

      

 

 

   

    試驗: max-active = 20 ,TPS 測試結果: TPS = 18000 <= max-active=10

    試驗: max-active = 30 ,TPS 測試結果: TPS = 10000

    結論: max-active 設置值范圍: 【10 ~ 20】

  2、Max-wait

    含義: 表示從連接池獲取連接的超時時間;單位是 ms ; 這個參數只管理獲取連接的超時時間。

    獲取連接造成線程等待超時的原因:

      (1)連接池未初始化(導致一開始獲取不到連接,導致超時)

      (2)連接長時間使用,已經被釋放

      (3)連接使用中,需要新建連接

      (4)連接池中連接耗盡,需要等待用完后歸還;

    推薦設置:內網狀態:max-wait=800 ms , 網絡狀態不是特別好,推薦設置大於等於 1200ms,因為 tcp 連接重試一般 1s;

    例子:Max-wait = 0 – 無限等待,大量流量涌入后,導致線程池隊列非常長,看起來 TPS 上升了,實際上處理吞吐能力下降的;

  3、連接屬性

    (1)connectionTimeout : 配置建立 TCP 連接的超時時間,追加到連接后面即可;

    (2)socketTimeout : 配置發送請求后,等待響應的超時時間,這里有個問題,如果建立了連接,但是在會話的時候,一直拿不到結果,那么該線程就一直阻塞,導致可用資源下降。

    結論:Jdbc 請求連接后面:&connectionTimeout=3000&socketTimeout=1200

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM