数据库连接池的手写核心逻辑是什么?

wen java案例 60

本文目录导读:

数据库连接池的手写核心逻辑是什么?

  1. 核心接口设计
  2. 核心数据结构
  3. 核心逻辑实现
  4. 连接验证机制
  5. 线程安全与连接超时
  6. 完整流程图
  7. 进阶优化点

数据库连接池的核心逻辑是复用数据库连接,避免频繁创建和销毁连接带来的性能开销(TCP三次握手、数据库认证等),手写一个简单的连接池,核心需要实现以下逻辑:

核心接口设计

public interface ConnectionPool {
    // 获取连接
    Connection getConnection() throws SQLException;
    // 归还连接
    void releaseConnection(Connection conn);
    // 关闭连接池
    void shutdown();
}

核心数据结构

public class SimpleConnectionPool implements ConnectionPool {
    // 空闲连接池(线程安全)
    private LinkedList<Connection> idleConnections = new LinkedList<>();
    // 活跃连接数
    private AtomicInteger activeCount = new AtomicInteger(0);
    // 最大连接数
    private int maxSize;
    // 最小连接数
    private int minSize;
    // 连接URL
    private String url, username, password;
}

核心逻辑实现

1 初始化连接池

// 预先创建最小数量的连接
public void init() throws SQLException {
    for (int i = 0; i < minSize; i++) {
        Connection conn = createConnection();
        idleConnections.addLast(conn);
    }
}
private Connection createConnection() throws SQLException {
    Connection conn = DriverManager.getConnection(url, username, password);
    // 关键:用代理模式包装连接,拦截close()方法
    return new ConnectionProxy(conn, this);
}

2 获取连接(核心方法)

@Override
public Connection getConnection() throws SQLException {
    // 从空闲队列获取
    Connection conn = getFromPool();
    if (conn != null) {
        // 验证连接是否有效
        if (validateConnection(conn)) {
            activeCount.incrementAndGet();
            return conn;
        } else {
            // 无效连接,丢弃并创建新的
            closeRealConnection(conn);
            conn = createNewConnection();
        }
    } else {
        conn = createNewConnection();
    }
    return conn;
}
private Connection getFromPool() {
    synchronized (idleConnections) {
        if (idleConnections.size() > 0) {
            return idleConnections.removeFirst();
        }
        return null;
    }
}
private Connection createNewConnection() throws SQLException {
    if (activeCount.get() < maxSize) {
        Connection conn = createConnection();
        activeCount.incrementAndGet();
        return conn;
    }
    // 超过最大连接数,等待或抛出异常
    throw new SQLException("连接池已满,最大连接数:" + maxSize);
}

3 归还连接(核心方法)

@Override
public void releaseConnection(Connection conn) {
    if (conn == null) return;
    activeCount.decrementAndGet();
    synchronized (idleConnections) {
        // 判断空闲池是否已满
        if (idleConnections.size() >= minSize) {
            // 空闲过多,关闭连接
            closeRealConnection(conn);
        } else {
            // 放回空闲池
            idleConnections.addLast(conn);
        }
    }
}

4 连接代理(关键设计)

public class ConnectionProxy implements Connection {
    private Connection realConnection;
    private ConnectionPool pool;
    // 包装实际连接
    public ConnectionProxy(Connection real, ConnectionPool pool) {
        this.realConnection = real;
        this.pool = pool;
    }
    @Override
    public void close() throws SQLException {
        // 拦截close(),改为归还连接
        pool.releaseConnection(this);
    }
    // 所有方法委托给真实连接
    @Override
    public Statement createStatement() throws SQLException {
        return realConnection.createStatement();
    }
    // ... 其他方法类似
}

连接验证机制

private boolean validateConnection(Connection conn) {
    try {
        // 简单验证:执行一个轻量级查询
        if (conn.isClosed()) return false;
        Statement stmt = conn.createStatement();
        stmt.execute("SELECT 1");
        return true;
    } catch (SQLException e) {
        return false;
    }
}

线程安全与连接超时

// 使用信号量控制并发获取连接
private Semaphore semaphore = new Semaphore(maxSize, true);
public Connection getConnectionWithTimeout(long timeout, TimeUnit unit) 
        throws SQLException, InterruptedException {
    if (semaphore.tryAcquire(timeout, unit)) {
        return getConnection();
    }
    throw new SQLException("获取连接超时");
}

完整流程图

[应用层] --getConnection()--> [连接池]
                               |
                ┌──────────────┴──────────────┐
                ↓                              ↓
        [空闲池有连接]                    [空闲池无连接]
                |                              |
             取连接 ─→ 验证有效否──→ 有效:返回  [判断连接数]
                |       |                      ↓
                |     无效                   [达到最大数?]
                |       ↓                    /        \
           丢弃连接   创建新连接           [是]        [否]
                |       |               等待/异常   创建新连接
                └───────┴──────────┘
                               |
                           [返回连接给应用]
                               |
                    [应用使用连接,然后close()]
                               |
                            [close()被拦截]
                               |
                     ┌─────────┴──────────┐
                     ↓                     ↓
                [空闲池未满]           [空闲池已满]
                     |                     |
                 放回空闲池              关闭连接

进阶优化点

  1. 连接泄露检测: 记录连接借出时间,超时自动回收
  2. 连接健康检查: 定时任务清理无效连接
  3. 扩展性: 支持不同数据源、连接属性配置
  4. 性能统计: 记录获取连接时间、命中率等指标

这个手写实现涵盖了连接池最核心的复用、代理、验证、线程安全逻辑,实际生产中的HikariCP、Druid等在此基础上增加了更多优化和监控功能。

抱歉,评论功能暂时关闭!