数据库连接池的模块设计
DriverManager 与 DataSource 的区别
DriverManger 使用 getConnection 获取数据库的连接,本质是与数据库建立连接
- 建立数据库连接操作是很耗费资源的操作,产生较大的系统开销
因此有了连接池的引用,使用池化思想:
- 提前创建好一些连接,供使用
- 将创建的资源缓存起来,避免频繁的创建连接,等待下一个使用者使用
DataSource 的引入
- 本质是提供数据库连接的服务类(数据源)
- 对DriverManger进行封装,建立一个中间层(DateSource),将DriverManger创建的连接存入Pool,外部从Pool获取连接。
1 |
|
- DataSource的形式是JNDI (Java Naming Directory Interface)
- 数据源的概念在应用程序与数据库连接之间插入了一个中间层,进而可以实现连接池以及事务管理,并且以JNDI的形式,也能够以非常方便的形式使用。
小结
DataSource 是基于应用程序与 DriverManager 抽象出来的中间层,解耦了应用程序与数据库的实际连接,类似代理模式可以添加更多的功能:连接池、分布式事务等。
连接池与DataSource是两回事,只是目前市面上实现了DataSource都赋予了连接池、连接池管理的功能。
HikariPool
设计模型
核心类 HikariDataSource 继承自 DataSource
核心成员 HikariPool pool(volatile 保证可见)实现连接池功能 继承自 PoolBase
字段:
DataSource 用于创建数据库连接(DriverDataSource Driver创建连接)
connectionBag 用于缓存数据库连接
1 |
|
addConnectionExecutor 单线程线程池 用于建立数据库连接 -> 线程池允许核心线程超时
executor.allowCoreThreadTimeOut(true);
closeConnectionExecutor 单线程线程池 用于关闭数据库连接 -> 线程池允许核心线程超时
executor.allowCoreThreadTimeOut(true);
houseKeepingExecutorService 调度线程池 内部定时器,用于实现连接的超时淘汰、连接池的补充等工作。
addConnectionQueueReadOnlyView -> addConnectionExecutor(线程池) 阻塞队列的集合 用来判断高并发时 超过MaxSize
1
2
3
4
5
6
7
8
9
final int maxPoolSize = config.getMaximumPoolSize();
LinkedBlockingQueue<Runnable> addConnectionQueue = new LinkedBlockingQueue<>(maxPoolSize);
this.addConnectionQueueReadOnlyView = unmodifiableCollection(addConnectionQueue);
this.addConnectionExecutor = createThreadPoolExecutor(addConnectionQueue, poolName + " connection adder", threadFactory, new ThreadPoolExecutor.DiscardOldestPolicy());
1 |
|
配置参数
maxLifeTime: 15m
底层执行一个延时任务,延时 maxLifeTime 便执行,给 Connection 打上驱逐标记 poolEntry.markEvicted(),如果当前连接是空闲连接 state; STATE_NOT_IN_USE,则直接真实关闭当前连接。若不是 只有等待连接空闲后,在getConnection 时,判断是否存在evict 标记,进行连接close
idleTimeout: 10s
minIdle: 1
底层使用一个定时线程池,执行一个定时任务默认 30ms 执行一次,扫描出空闲连接,并进行清理。(保证剩余的线程)
tip 通过 Semaphore 信号量并发工具 实现线程池的暂停功能
- 核心思想:将信号量消耗完,获取信号量的最大值,,其余获取消耗量的线程都阻塞
1 |
|
tip (PoolEntry 状态字段state)
- AtomicIntegerFieldUpdater 用于原子性(线程安全)更新类对象中的int字段
JDBCTemplate
1 |
|
tip Collection.unmodifiableCollection()
- 创建/封装 不可变集合
UnmodifiableCollection
,代理模式,重写修改的方法 抛出异常
1 |
|