1.mysql
1.1. mysql 引數
透過下列命令可檢視mysql資料庫配置的系統引數:
-- 查詢所有系統引數
show variables;
--模糊匹配查詢系統引數,如:wait_timeout
show variables like '%wait_timeout%';
這裡介紹幾個和連線池有關聯的引數:
1. wait_timeout
非互動連線的最大存活時間,單位:秒。即空閒狀態下的連線,超過規定時間後,mysql 會自動斷開。
可透過下列命令檢視具體的連線的狀態:
show processlist;
如果 sleep 狀態的程式,佔用總比例過高,就可以考慮調小 wait_timeout 值了。
2. max_connections
全域性最大連線數。
可透過下列命令檢視最大使用的連線數量(Max_used_connections):
show status like 'max%connections%';
再透過下列命令檢視最大連線數(max_connections):
show variables like 'max%connections%';
透過 Max_used_connections/max_connections
的佔比來判斷設定的最大連線數是否合理,理想情況下這個比例應該在85%左右。
max_connections 預設值是100,如果伺服器的併發連線請求量比較大,建議調高此值,以增加並行連線數量,當然這建立在機器能支撐的情況下,因為如果連線數越多,介於MySQL會為每個連線提供連線緩衝區,就會開銷越多的記憶體,所以要適當調整該值,不能盲目提高設值。
1.2. druid 連線池配置
核心引數
1. initial-size
初始化時建立物理連線的個數。
2. max-active
連線池同時能維持的最大連線數。
3. min-idle
最多維持多少個空閒連線,即使客戶端沒有需求,也要至少維持多少個空閒連線,以應對客戶端的突發需求。
4. max-idle(已作廢)
5. max-wait
連線最大等待時間,單位毫秒。客戶端從連線池獲取(借出)一個連線後,規定時間內沒有歸還,則連線池會丟擲 GetConnectionTimeoutException 異常。
場景模擬
假設配置的值如下:
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=10
spring.datasource.druid.max-active=50
專案啟動時,會自動建立5(initial-size
)個連線,就算此時沒有資料庫訪問,也會建立這5個。並且當客戶端查詢資料庫的併發不大於5時,就一直是這5個。
當客戶端查詢資料庫的併發越來越大,超過5時,連線數也就往上增加,但不會超過最大連線數50(max-active
)。當併發數超過50時,超過部分的請求就會在佇列中等待。
當峰值過去了,併發數降到50一下,多出來的連線空閒後就關閉了,連線數也就隨之下降。當連線數最小隻會降到10(min-idle
),最多維持10個空閒連線。
1.3. hikari 連線池配置
下列翻譯自 HikariCP Github引數說明:
1. connection-timeout
控制客戶端等待來自連線池連線的最大毫秒數。
如果超過此時間而沒有可用的連線,則會丟擲SQLException。可接受的最低連線超時為250 ms。 預設值:30000(30秒)
2. max-lifetime
控制連線池中連線的最大生存時間。
正在使用中的連線永遠不會停止使用,只有在連線關閉後,在達到最大生存週期後才將其刪除。值為0表示沒有最大生存期(無限生存期),當然這取決於idleTimeout設定。最小允許值是30秒,預設值:30分鐘。
建議:設定的時間要比資料庫中限制的連線(mysql對應引數 wait_timeout
)最大生存時間小几秒鐘。
3. minimum-idle
此屬性控制HikariCP試圖在池中維護的最小空閒連線數。
如果空閒連線低於此值,並且池中的總連線小於最大池大小,HikariCP將盡最大努力快速高效地新增其他連線。預設值:與 maximum-pool-size 相同。
建議:為了最大限度地提高效能和響應峰值需求,我們建議不要設定此值,而是允許HikariCP充當固定大小的連線池。即保持和 maximum-pool-size 值相同。
4. idle-timeout
此屬性控制允許連線在池中空閒的最長時間。
僅當 minimum-idle 定義為小於 maximum-pool-size 時,此設定才適用。一旦池達到最小空閒連線數,空閒連線將不會失效。連線是否因空閒而失效取決於+30秒的最大變化和+15秒的平均變化。在此超時之前,連線永遠不會以空閒狀態退出。值為0表示從不從池中刪除空閒連線。最小允許值為10000ms(10秒)。預設值:600000(10分鐘)。
建議:因為是建議 minimum-idle 和 maximum-pool-size 保持一致,維護固定大小的連線池,則 idle-timeout 設定不會生效。建議就保持預設值,或者乾脆設為0。
5. maximum-pool-size
此屬性控制池允許達到的最大大小,包括空閒連線和正在使用的連線。基本上,該值將確定到資料庫後端的實際連線的最大數量。當池達到此大小且沒有空閒連線可用時,對getConnection() 的呼叫將在超時前阻塞最多 connection-timeout 毫秒。預設值:10。
建議:沒有絕對的值,因為是連線池的最大連線數,所以要根據產線業務 TPS 併發量,以及伺服器實際配置各種環境來靈活考量配置,影響因素如下:
- CPU核心數:首先網上有這麼個公式:
最大連線數 = ((CPU核心數 * 2) + 有效磁碟數)
。可見,最大連線數是和CPU核心數是密切相關的。因為最大連線數是和最大併發執行緒相關的,當CPU核心數有限時,一味的擴大併發連線數,反而會因為上下文切換導致效能下降。 - 資料庫總連線數: 應用連線池的配置是針對某個服務單例項的,但通常一個資料庫是多個服務共享的。假設有10個服務,每個服務平均有8個例項負載,單個連線池的最大連線數設為50。那麼總的連線數就是 10 8 50 = 4000。而如果mysql資料庫的 max_connections 不到4000,那麼必然會導致有些連線失效。
2. redis
2.1. redis 引數
1. 檢視允許最大連線數量
執行命令:
config get maxclients
返回結果示例,即最大連線數10000:
maxclients
10000
2. 檢視實時連線數量
info clients
返回結果示例,依次返回的內容有:(1)當前客戶端連線數、(2)當前所有輸出快取區中佇列物件個數的最大值、(3)當前所有輸出快取區中佔用的最大容量、(4)正在等待阻塞命令(如:BLPOP)的客戶端數量
# Clients
connected_clients:39
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:1
2.2. jedis 連線池配置
1. max-total
(max-active)
資源池中的最大連線數。預設值:8。舊版本中是 max-active
,jedis 2.4.x 以上都用 max-total 來替代。
想合理設定maxTotal(最大連線數)需要考慮的因素較多,如:
- 業務希望的Redis併發量;
- 客戶端執行命令時間;
- Redis資源,例如 nodes * maxTotal 不能超過Redis的最大連線數;
- 資源開銷,例如雖然希望控制空閒連線,但又不希望因為連線池中頻繁地釋放和建立連線造成不必要的開銷。
假設一次命令時間,即borrow|return resource加上Jedis執行命令 ( 含網路耗時)的平均耗時約為1ms,一個連線的QPS大約是1s/1ms = 1000,而業務期望的單個Redis的QPS是50000(業務總的QPS/Redis分片個數),那麼理論上需要的資源池大小(即MaxTotal)是50000 / 1000 = 50。
但事實上這只是個理論值,除此之外還要預留一些資源,所以maxTotal可以比理論值大一些。
這個值不是越大越好,一方面連線太多會佔用客戶端和服務端資源,另一方面對於Redis這種高QPS的伺服器,如果出現大命令的阻塞,即使設定再大的資源池也無濟於事。
綜上所述,在沒有達到資源瓶頸前,jedis 最大連線數和能實現併發量是成正比的。如果處於高併發的需求,可以多加連線數。
2. max-idle
資源池允許的最大空閒連線數。預設值:8。
maxIdle實際上才是業務需要的最大連線數,maxTotal 是為了給出餘量,所以 maxIdle 不要設定得過小,否則會有new Jedis(新連線)開銷,而minIdle是為了控制空閒資源檢測。
連線池的最佳效能是 maxTotal=maxIdle
,這樣就避免了連線池伸縮帶來的效能干擾。如果您的業務存在突峰訪問,建議設定這兩個引數的值相等;如果併發量不大或者maxIdle設定過高,則會導致不必要的連線資源浪費。
可以根據實際總QPS和呼叫Redis的客戶端規模整體評估每個節點所使用的連線池大小。在實際環境中,比較可靠的方法是透過監控來嘗試獲取引數的最佳值。可以考慮透過JMX等方式實現監控,從而找到合理值。
3. min-idle
資源池允許的最小空閒連線數。預設值:0。
4. block-when-exhausted
當資源池用盡後,呼叫者是否要等待。只有當值為true時,下面的max-wait-millis才會生效。預設值:true。
5. max-wait-millis
(max-wait)
當資源池連線用盡後,呼叫者的最大等待時間(單位為毫秒)。預設值:-1(表示永不超時)。舊版本中是 max-wait
,jedis 2.4.x 以上都用 max-wait-millis 來替代。
2.3. lettuce 連線池配置
1. max-total
連線池最大連線數(使用負值表示沒有限制)。預設值:8。
推薦:cpu核數*2。
2. max-idle
連線池最大空閒連線數(使用負值表示沒有限制),僅當 min-idle 和 time-between-eviction-runs 的值都為正時有效。。預設值:8。
推薦:cpu核數*2。
3. min-idle
連線池最小空閒連線數,僅當 min-idle 和 time-between-eviction-runs 的值都為正時有效。預設值:0。
推薦:根據時間場景,是否需要初始化預熱等等。
4. time-between-eviction-runs
空閒連線逐出器(獨立執行緒)的執行間隔時間(單位為毫秒)。當值為正值時,空閒連線逐出器才啟動。
這個逐出器的任務一旦啟動後,不僅可以將連線池中超過 max-idle
數量的空閒連線逐出;還會在連線池中空閒連線數少於 min-idle
時,補齊空閒連線的建立。
推薦:正值,開啟任務。
5. max-wait
連線池資源耗盡時,連線嘗試分配阻塞時間(單位為毫秒),超時即丟擲異常。(使用負值表示沒有限制)。預設值:-1ms。
推薦:開啟,根據業務設定,不建議設定過大,否則耗盡業務執行緒池。
2.4. 場景模擬
Jedis 和 Lettuce 採用的連線池是 GenericObjectPoolConfig 所以通用的配置項是相同的,那麼就都基於統一配置做場景模擬。
場景一
xxx.max-total=30
xxx.max-idle=20
xxx.min-idle=10
當連線池剛啟動,且空閒連線數不超過10。如果需要使用連線時,連線池會一直建立新連線,而不會複用空閒連線。直到連線池中連線數量達到了10(min-idle)。
當連線數超過10,實際連線數又繼續增加,但由於總連線數 max-total 是30。當總連線數達到30後,不會建立新的連線,後續連線請求會在等待。
當實際使用的連線數從30降下來後,一部分連線轉為了空閒連線。即:在用連線數量在減少,空閒連線數量在增加。但當空閒連線數量大於20(max-idle)時,後續的空閒連線將不會放回連線池,而是直接扔掉。
2.5. jedis vs lettuce
簡單的說, Jedis連線池越大越好, Lettuce連線池越小越好, 為什麼會有這種差異?
Jedis採用傳統BIO網路模型, 在資源允許的範圍內, 這種模型下連線數(執行緒數)越多效能越好。
Lettuce採用NIO網路模型, 底層元件採用Netty, 這種模型下效能和CPU核數相關, 通常雲主機CPU核數都不大通常在2-16核, 因此Lettuce連線池配置普遍不宜過大, 過大範圍會影響效能。