本文介紹基於MySQL JDBC串連池Druid串連並訪問Lindorm寬表引擎的使用方法。
前提條件
已開通MySQL協議。如何開通,請參見開通MySQL協議相容功能。
已安裝Java環境,要求安裝JDK 1.8及以上版本。
已將用戶端IP添加至白名單,具體操作請參見設定白名單。
注意事項
Lindorm前端接入節點使用SLB做負載平衡,用戶端串連前端節點。為了將用戶端請求較為均勻地發送到各個前端節點,建議串連保持的時間不宜太長,可以配置phyMaxUseCount和phyTimeoutMillis參數。
執行查詢前從串連池擷取串連,執行完查詢後要及時調用
conn.close()將串連返回到串連池中。再次使用時,請從串連池中擷取新串連,避免長時間使用一個串連導致Druid無法及時檢查到串連失效。在複雜網路環境下,若遇到網關效能達到瓶頸、網路鏈路長、網路抖動、重傳率或丟包率高等情況,可能會導致串連中斷。建議確保串連池配置合理,並在必要時通過業務代碼側的重試機制最佳化。
服務端升級重啟時,串連可能會短暫中斷。即使使用了串連池,業務側仍可能感知到異常。建議捕獲異常並重試。
根據業務情況合理調整串連池配置,並確保配置生效。您可以在程式中通過
DruidDataSource#getStatData()和DruidDataSource#dump()方法定期擷取生效的配置與串連池的資訊,並在日誌中查看、核對相關配置資訊。
操作步驟
通過串連池Druid串連Lindorm寬表引擎前,需要安裝串連池Druid和Lindorm JDBC Driver。
以Maven專案為例,在
pom.xml檔案的dependencies中添加以下依賴項。<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.11</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.3.0</version> </dependency>如果您是通過druid-spring-boot-starter使用Druid串連池,則需要先排除druid-spring-boot-starter依賴的druid組件,再顯式依賴druid組件,具體代碼如下所示。
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.11</version> <exclusions> <exclusion> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.11</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.3.0</version> </dependency>配置串連池Druid的參數。在Maven專案的
src/main/resources目錄中建立druid.properties檔案,並在檔案中添加以下內容。# 驅動類名,無需替換 driverClassName=com.mysql.cj.jdbc.Driver # url為Lindorm寬表引擎MySQL協議的JDBC串連地址,username、password為寬表引擎的使用者名稱及密碼,可以在Lindorm控制台上擷取。 # database為需要串連的資料庫,需替換為實際使用的資料庫名稱。其他參數建議保持不變,對效能有一定協助。 url=jdbc:mysql://ld-uf6k8yqb741t3****-proxy-sql-lindorm-public.lindorm.rds.aliyuncs.com:33060/database?sslMode=disabled&allowPublicKeyRetrieval=true&useServerPrepStmts=true&useLocalSessionState=true&rewriteBatchedStatements=true&cachePrepStmts=true&prepStmtCacheSize=100&prepStmtCacheSqlLimit=50000000&socketTimeout=120000 username=**** password=**** # 初始化串連池即建立串連,建議保持不變 init=true # 初始化串連池時建立串連的個數,可以根據實際情況調整 initialSize=10 # 串連池中允許的最大串連數量,可以根據實際情況調整,建議和業務線程池大小相同 maxActive=40 # 串連池中維護的空閑串連的數量,可以根據實際情況調整.對效能要求高的情境建議和maxActive的值相同,如果業務存在明顯的峰穀波動,建議設定小一些 minIdle=40 # 擷取串連最大等待時間,單位毫秒(ms),建議保持不變 maxWait=30000 #配置一個串連最大使用次數,避免長時間使用相同串連造成伺服器端負載不均衡,對效能有略微影響 druid.phyMaxUseCount=10000 # 串連保活配置項,建議保持不變,否則可能出現串連斷開 druid.keepAlive=true # 串連空閑多久以後,會檢查串連的有效性 druid.keepAliveBetweenTimeMillis=120000 # 多久執行一次淘汰串連和保活操作 timeBetweenEvictionRunsMillis=60000 #空閑串連淘汰時間 minEvictableIdleTimeMillis=300000 maxEvictableIdleTimeMillis=600000 phyTimeoutMillis=1800000 # 串連驗證配置項,建議保持不變 testWhileIdle=true testOnBorrow=false testOnReturn=false參數說明
參數
說明
url
MySQL協議的Java JDBC串連地址。格式為
jdbc:mysql://<MySQL相容地址>/<資料庫名>?<串連配置>。資料庫名不填寫時預設串連default資料庫。如何擷取MySQL相容地址,請參見查看串連地址。
串連配置可以有效提升效能,建議全部填寫,詳細說明,請參見串連配置說明。
重要如果應用部署在ECS執行個體,建議您通過專用網路訪問Lindorm執行個體,以獲得更高的安全性和更低的網路延遲。
如果應用部署在本地,在通過公網串連Lindorm執行個體前,需在控制台開通公網地址。開通方式:在控制台選擇,在宽表引擎頁簽單擊开通公网地址。
通過專用網路訪問Lindorm執行個體,url中請填寫MySQL相容地址對應的专有网络地址。通過公網訪問Lindorm執行個體,url中請填寫MySQL相容地址對應的公网地址。
username
如果您忘記使用者密碼,可以通過Lindorm寬表引擎的叢集管理系統修改密碼。具體操作,請參見修改使用者密碼。
password
載入串連池Druid的參數並初始化串連池Druid。
// 載入參數 Properties properties = new Properties(); InputStream inputStream = DruidPoolDemo.class.getClassLoader().getResourceAsStream("druid.properties"); properties.load(inputStream); // 初始化串連池 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);通過串連池Druid擷取JDBC的串連資訊並訪問Lindorm寬表引擎。
/* -------------- 基於JDBC的訪問樣本 ----------------- */ String tableName = "sql_table_" + new Random().nextInt(1000); // 建立表 try (Connection connection = dataSource.getConnection()) { try (Statement statement = connection.createStatement()) { String sql = "create table if not exists " + tableName + "(id VARCHAR, name VARCHAR, primary key(id))"; int ret = statement.executeUpdate(sql); System.out.println(ret); } } // 插入資料 try (Connection connection = dataSource.getConnection()) { String sql = "insert into " + tableName + "(id,name) values(?,?)"; try (PreparedStatement ps = connection.prepareStatement(sql)) { ps.setString(1, "aa"); ps.setString(2, "bb"); int ret = ps.executeUpdate(); System.out.println(ret); } } //批量寫入資料 String insertSql = "insert into " + tableName + "(id,name) values(?,?)"; int batchSize =100; try (Connection connection = dataSource.getConnection()) { try (PreparedStatement ps = connection.prepareStatement(insertSql)) { for (int i = 0; i < batchSize; i++) { ps.setString(1, "aa" + i); ps.setString(2, "bb" + i); //加入批次 ps.addBatch(); } //批次寫入 ps.executeBatch(); } } // 查詢資料 try (Connection connection = dataSource.getConnection()) { String sql = "select * from " + tableName + " where id=?"; try (PreparedStatement ps = connection.prepareStatement(sql)) { ps.setString(1, "aa"); ResultSet rs = ps.executeQuery(); while (rs.next()) { String id = rs.getString(1); String name = rs.getString(2); System.out.println("id=" + id); System.out.println("name=" + name); } } } // 刪除資料 try (Connection connection = dataSource.getConnection()) { String sql = "delete from " + tableName + " where id=?"; try (PreparedStatement ps = connection.prepareStatement(sql)) { ps.setString(1, "aa"); ps.executeUpdate(); } }說明在Lindorm SQL中,
insert語句的語義與upsert相同。由於MySQL JDBC的用戶端最佳化了insert語句,因此在寫入資料時更推薦您使用insert語句。Batch寫入比單行寫入更能節省RPC次數,伺服器能夠批量處理行寫入,更容易達到更大的吞吐。但Batche寫入如果一次性寫入過多的行,可能會導致伺服器OOM或Full GC,進而影響服務穩定性。因此,建議您將Batch寫入的行數控制在合理範圍內,batchSize為Batch的行數,建議設定為50~100。
您可以通過增加寫入並發的方式增加寫入吞吐。
常見問題
Q:串連時報錯Read timed out是什麼原因?
A:Druid串連池預設逾時時間為10秒,因此會出現Read timed out報錯。您可以在串連串中添加socketTimeout參數來設定逾時時間,單位為毫秒(ms)。例如設定逾時時間長度為2分鐘(120,000毫秒):jdbc:mysql://ld-uf6k8yqb741t3****-proxy-sql-lindorm-public.lindorm.rds.aliyuncs.com:33060/" + database + "?sslMode=disabled&allowPublicKeyRetrieval=true&useServerPrepStmts=true&useLocalSessionState=true&rewriteBatchedStatements=true&cachePrepStmts=true&prepStmtCacheSize=100&prepStmtCacheSqlLimit=50000000&socketTimeout=120000
附錄:串連池負載平衡說明
串連池模式(TCP長串連)的效率更高,但在以下情境中對分布式負載平衡不友好,可能導致串連負載不均勻:
突發建立大量串連,導致分布不均
當應用突發建立了大量的串連時,若負載平衡裝置未能及時重新整理後端節點的串連統計資訊,可能會導致部分後端LDServer節點承載較多的串連請求。同時,疊加串連池化機制,最終會導致部分LDServer節點壓力高於其他節點,串連分布不均,影響系統總體效能。
負載平衡探活異常,導致分布不均
負載平衡通過主動探活來判斷後端節點是否正常,當探活出現偶發異常時,可能會導致部分LDServer節點上串連較少,結合串連池化,最終會導致部分LDServer壓力低於其他節點,影響系統總體效能。
Druid串連池增加了phyTimeoutMillis和phyMaxUseCount參數,定期(例如每執行30分鐘或者10,000次)重新整理串連池中的串連,可以在解決上述問題的同時保持效能基本不變,建議預設添加這兩個參數。