一、druid 多數據源卡頓
在使用 druid 多數據源的過程中,有時候我們會遇到卡頓的情況。這主要是因為多個數據源使用同一連接池,這會導致連接池資源的競爭。因此,為了解決這個問題,我們可以考慮對每個數據源都單獨建立一個連接池。
@Bean(name = "ds1")
@ConfigurationProperties(prefix = "spring.datasource.ds1")
public DataSource ds1() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "ds2")
@ConfigurationProperties(prefix = "spring.datasource.ds2")
public DataSource ds2() {
return DruidDataSourceBuilder.create().build();
}
在每個數據源的配置中加入 initialSize
和 maxActive
屬性,分別設置連接池的初始大小和最大連接數,以避免資源競爭問題。
# 連接池初始大小
spring.datasource.druid.initialSize=5
# 連接池最大活躍數量
spring.datasource.druid.maxActive=20
二、druid 多數據源監控頁面
druid 多數據源提供了監控頁面,用於查看連接池的狀態與連接信息。我們只需要在項目中引入 druid 的監控依賴,並進行相應的配置即可。
com.alibaba
druid-spring-boot-starter
1.1.20
在項目配置文件中加入監控頁面的相關配置。
## druid的相關部分
# 激活監控功能,允許訪問druid監控頁面
spring.datasource.druid.stat-view-servlet.enabled=true
# 配置druid監控頁面的訪問路徑
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
# 監控用戶的賬號密碼,不設置則可輸入任意賬號密碼進入監控頁面
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
三、druid 多數據源配置
在使用 druid 多數據源的過程中,我們需要在項目中配置多個數據源。這裡我們給出一個簡單的配置示例。
## 資料庫1的相關配置
spring.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.ds1.url=jdbc:mysql://localhost:3306/test1
spring.datasource.ds1.username=root
spring.datasource.ds1.password=123456
## 資料庫2的相關配置
spring.datasource.ds2.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.ds2.url=jdbc:mysql://localhost:3306/test2
spring.datasource.ds2.username=root
spring.datasource.ds2.password=123456
四、druid 多數據源切換
在使用 druid 多數據源時,我們需要切換數據源。這裡我們介紹兩種切換數據源的方法。
方法一:利用 @Qualifier
註解指定數據源名稱,實現數據源的動態切換。
@Autowired
private ApplicationContext context;
// 切換數據源,指定數據源名稱
public void changeDataSource(String dataSourceName) {
DataSource dataSource = (DataSource) context.getBean(dataSourceName);
DynamicDataSourceContextHolder.setDataSource(dynamicDataSource);
}
方法二:使用多線程與 ThreadLocal 實現數據源的動態切換。
static class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSource();
}
}
public class DynamicDataSourceContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal();
public static void setDataSource(String dataSourceName) {
contextHolder.set(dataSourceName);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
五、druid 多數據源監控
druid 多數據源提供了多種監控指標,包括連接數、並發請求數、SQL 運行時間、錯誤數等。
## 配置druid監控統計功能
# 數據源監控開關
spring.datasource.druid.stat.enable=true
# 配置druid監控統計持續的時間
spring.datasource.druid.stat.time-between-log-stats-millis=60000
# 慢SQL查詢閾值
spring.datasource.druid.filter.slowsql.enabled=true
spring.datasource.druid.filter.slowsql.time-threshold=1000
# 啟用mergeSql功能
spring.datasource.druid.filter.stat.merge-sql=true
# SQL合併的閾值
spring.datasource.druid.filter.stat.slow-sql-millis=1000
六、druid 數據源配置
除了多數據源方案,我們還可以對單個數據源進行配置。可以配置以下選項:初始大小、最大連接數、最小連接數、獲取連接的最大等待時間、回收連接的最大等待時間、是否進行前綴截斷、是否緩存 Statement、是否允許進行多條 SQL 合併等。
## 數據源的相關配置
spring.datasource.initialSize=5 # 初始化連接數量
spring.datasource.maxActive=10 # 最大連接數量
spring.datasource.minIdle=2 # 最小空閑連接數量
spring.datasource.maxWait=60000 # 獲取連接的最大等待時間,單位毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000 # 連接回收的時間間隔,單位毫秒
spring.datasource.minEvictableIdleTimeMillis=300000 # 連接可被回收的最大空閑時間,單位毫秒
spring.datasource.testWhileIdle=true # 測試連接是否有效
spring.datasource.validationQuery=SELECT 1 FROM DUAL # 驗證 SQL 語句
spring.datasource.testOnBorrow=false # 是否在從池中取出連接前進行檢驗
spring.datasource.testOnReturn=false # 是否在歸還到池中前進行檢驗
spring.datasource.poolPreparedStatements=true # 是否緩存 Statement 對象
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 # 開啟緩存後,每個連接允許緩存的 Statement 對象數量
# 開啟對多條 SQL 語句合併批量更新操作的支持,例如 insertBatch,updateBatch 等
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
七、druid 多數據源事務
在使用 druid 多數據源時,需要對事務進行特別的處理。我們需要使用 Spring 的 @Transactional
註解,在方法級別上進行事務的註解。同時,我們還需要在每個數據源上綁定單獨的事務管理器。
@Bean(name = "transactionManager1")
public DataSourceTransactionManager transactionManager1() {
return new DataSourceTransactionManager(ds1());
}
@Bean(name = "transactionManager2")
public DataSourceTransactionManager transactionManager2() {
return new DataSourceTransactionManager(ds2());
}
之後,在需要使用事務的方法上加入 @Transactional
註解,並指定數據源名稱。
@Transactional(value = "transactionManager1")
public void saveUser(User user) {
userDao.insert(user);
}
@Transactional(value = "transactionManager2")
public void saveOrder(Order order) {
orderDao.insert(order);
}
八、druid 多數據源連接超時
在使用 druid 多數據源時,我們可能會遇到連接超時的問題。我們可以通過設置超時時間來解決這個問題。
spring.datasource.druid.time-between-eviction-runs-millis=60000 # 連接回收的時間間隔,單位毫秒
spring.datasource.druid.min-evictable-idle-time-millis=300000 # 連接可被回收的最大空閑時間,單位毫秒
spring.datasource.druid.max-evictable-idle-time-millis=1800000 # 連接池中連接的最大超時時間,單位毫秒
九、druid 多數據源創建及使用
在使用 druid 多數據源時,我們需要先創建多個數據源,之後再根據實際情況使用相應的數據源。
@Configuration
public class DataSourceConfig {
@Bean(name = "ds1")
@ConfigurationProperties(prefix = "spring.datasource.ds1")
public DataSource ds1() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "ds2")
@ConfigurationProperties(prefix = "spring.datasource.ds2")
public DataSource ds2() {
return DruidDataSourceBuilder.create().build();
}
}
@Component
public class DataSourceUtil {
// 注入所有數據源
@Autowired
@Qualifier("ds1")
private DataSource ds1;
@Autowired
@Qualifier("ds2")
private DataSource ds2;
public void execute() {
// 使用ds1數據源
Connection conn = ds1.getConnection();
...
// 使用ds2數據源
conn = ds2.getConnection();
...
}
}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/247936.html