如何设计数据库连接池

如何设计数据库连接池

曾经在面试的时候,就被问到如何设计连接池。当时就没有回答上来,就与offer擦肩而过。今天就来动手写一个简易版数据库连接池。

为什么需要连接池?数据库连接是一种比较宝贵资源,其创建或销毁都需要系统的开销。如果频繁创建、销毁,那势必会造成系统性能低下。为了提高资源的复用性,我们可以把创建的连接放入池中,需要的时候从池中获取,不需要的时候归还到池。这样我们就大大节省系统资源开销,还提高系统的性能。

难点

设计数据库连接池的难点在于:如何去归还到池中。

所用技术

动态代理:动态代理也可以理解为拦截器,可以在调用方法之前,去做一些事情。
JDK的代理基于接口,需要实现 InvocationHandler 接口
这里给出一个简单的例子。

public class Test {
   

    public static void main(String[] args) {
   
        A proxy = (A)Proxy.newProxyInstance(A.class.getClassLoader(), new Class[]{
   A.class}, new B());
        proxy.close();  // 打印方法名
    }

    interface A {
   
        void close();
    }

    static class B implements InvocationHandler {
   
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
            System.out.println(method.getName());
            return null;
        }
    }
}

动态代理其实是JVM在运行期动态帮我们创建接口 A 的实例。动态创建的代理类大概是这个样子的。

public class AProxy implements A {
   
	InvocationHandler handler;
	public AProxy(InvocationHandler handler) {
   
		this.handler = handler;
	}
	@Override
	public void close() {
   
		handler.invoke(this, A.class.getMethod("close"), new Object[]{
   });
	}
}
数据库连接池

mybatis 中就实现数据库连接池,这里根据mybatis源码去掉一些统计功能,写一个简易的数据库连接池,便于我们能够理解其中设计原理。
数据库连接池有几个参数:最大活跃数、最大空闲数、最大空闲时间。

PoolState

PoolState 类是用来存放活跃的连接和空闲连接。

public class PoolState {
   
    private final List<PoolConnection> activeConnections = new ArrayList<>();
    private final List<PoolConnection> idleConnections = new ArrayList<>();

    public List<PoolConnection> getActiveConnections() {
   
        return activeConnections;
    }

    public List<PoolConnection> getIdleConnections() {
   
        return idleConnections;
    }
}
PoolConnection

PoolConnection 类对 Connection 进行一层包装。它实现 InvocationHandler 主要用来在调用 close 方法时,并不是真正去关闭数据库,而是把连接放回到连接池中(poolDataSource)。PoolConnection 类有两个Connection对象,realConnection是数据库连接实例,proxyConnection是JVM动态地创建Connection的对象。客户端拿到的是proxyConnection 对象。

public class PoolConnection implements InvocationHandler {
   
    private final static String CLOSE = "close";
    private static final Class<?>[] IFACES = new Class<?>[] {
    Connection.class };

    private final PoolDataSource dataSource;
    private final Connection realConnection;
    private final Connection proxyConnection;
    private long keepAliveTime;

    public PoolConnection(Connection conn, PoolDataSource dataSource
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值