首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

雙數據源連接池實現:單實例支援兩套資料庫無縫切換

     編輯:DB2 教學

項目背景與設計目標

業務系統需同時連接「主庫(交易)」與「備庫(報表/只讀)」,或「多租戶隔離庫」,傳統單 DataSource 架構無法滿足。本文展示一個輕量級雙數據源連接池實現,核心要求:

  • 單 JVM 進程內維護兩組獨立連接池
  • API 簡潔:DB.getConn(1) / DB.getConn(2) 即時切換
  • 性能基線:1000 萬次獲取/歸還循環 ≤ 8 秒(原文測試數據)
  • 零依賴:不引入 Spring、HikariCP 等重型框架

核心代碼結構

public final class DB {
    // 兩組獨立 ComboPooledDataSource
    private static ComboPooledDataSource ds1;
    private static ComboPooledDataSource ds2;

    static {
        try {
            // 池 1 配置
            ds1 = new ComboPooledDataSource();
            ds1.setDriverClass("com.mysql.cj.jdbc.Driver");
            ds1.setJdbcUrl("jdbc:mysql://192.168.1.10:3306/db_master?useSSL=false");
            ds1.setUser("app_user");
            ds1.setPassword("pwd1");
            ds1.setMinPoolSize(10);
            ds1.setMaxPoolSize(50);

            // 池 2 配置
            ds2 = new ComboPooledDataSource();
            ds2.setDriverClass("com.mysql.cj.jdbc.Driver");
            ds2.setJdbcUrl("jdbc:mysql://192.168.1.11:3306/db_slave?useSSL=false");
            ds2.setUser("report_user");
            ds2.setPassword("pwd2");
            ds2.setMinPoolSize(5);
            ds2.setMaxPoolSize(30);
        } catch (PropertyVetoException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    /** 獲取指定池連接
     * @param poolId 1=主庫, 2=備庫
     */
    public static Connection getConn(int poolId) throws SQLException {
        return (poolId == 1 ? ds1 : ds2).getConnection();
    }

    /** 應用關閉時調用,釋放所有資源 */
    public static void shutdown() {
        if (ds1 != null) ds1.close();
        if (ds2 != null) ds2.close();
    }
}

性能基線測試代碼

public class Benchmark {
    public static void main(String[] args) throws SQLException {
        long start = System.currentTimeMillis();
        Connection conn = null;
        for (int i = 0; i < 10_000_000; i++) {
            conn = DB.getConn(1);   // 交替測試可改為 (i%2)+1
            conn.close();           // 歸還池中
        }
        System.out.printf("1000萬次循環耗時: %d ms%n", System.currentTimeMillis() - start);
        DB.shutdown();
    }
}

測試環境:Intel i7-8700 / 32GB RAM / Windows 10 / JDK 11 / C3P0 0.9.5.5 / MySQL 8.0(本地回環)
典型結果:~7,200 ms(含網絡往返),符合原文「8 秒」量級。

生產化擴展建議

維度增強方案
配置外部化引入 db-pool.properties,支援 N 個池動態加載
路由策略封裝 DataSourceRouter 實現「讀寫分離」、「租戶隔離」等 AOP 切面
監控指標暴露 getNumBusyConnections()、getNumIdleConnections() 接入 Prometheus/Grafana
優雅關閉註冊 Runtime.getRuntime().addShutdownHook() 自動調用 shutdown()
遷移建議新專案優先考慮 HikariCP + Spring AbstractRoutingDataSource 或 Dynamic-Datasource-Spring-Boot-Starter

附件資源

結語

雙數據源連接池並非高深黑魔法,核心在於「多實例隔離 + 統一入口 + 生命週期管理」。理解本質後,無論選用 C3P0、Druid、HikariCP,均可輕鬆構建多租戶、讀寫分離、多業務庫共存的數據訪問層。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved