池化技术
池化技术简单地说就是复用现成的资源,减少资源对象的创建次数,在高并发的场景下提高程序的响应速度。具体实现包括线程池、内存池、连接池、对象池等等。
使⽤池化技术缓存的资源对象有如下共同特点:
- 对象创建时间⻓;
- 对象创建需要⼤量资源;
- 对象创建后可被重复使⽤
数据库连接池即是在程序启动时就预先建⽴⾜够的数据库连接,并将这些连接通过一个容器组织起来,由程序动态地对池中的连接进⾏申请,使⽤,释放。
创建数据库连接是⼀个很耗时的操作,也容易对数据库造成安全隐患。所以,在程序初始化的时候,集中创建多个数据库连接,并把他们集中管理,供程序使⽤,可以保证较快的数据库读写速度,还更加安全可靠。
Mysql连接池
影响Mysql连接建立速度的两个主要因素是TCP的连接过程和Mysql的认证过程,使用连接池可减少这两个过程执行的次数,从而达到提高数据库访问速度的目的。
Mysql的客户端C API可参考mysql api c客户端。
实现思路
- 使用List作为容器存储连接,实现一个连接池类接口和连接类接口
连接池类接口是一个纯虚类,提供通用的连接管理服务,主要是创建新连接以及向之申请连接和收回连接。已创建的空闲连接挂在m_free_list
上,正在被使用的连接挂在m_busy_list
上。使用连接池之前可以先初始化这个池,也就是可以先建立一定的连接作为热备用。之后如果已建立的备用都用完了,再申请新连接投入使用。直至连接数达到允许的最大值,此时若线程再想申请连接则必须等待,可以选择死等(永久阻塞)或超时退出。
这个连接池类ConnPool
可以用于任何类型的连接管理。
/* 连接类接口 */
class Conn
{
public:
virtual ~Conn() {
};
virtual int init() = 0;
};
/* 连接池类接口 */
class ConnPool
{
public:
ConnPool() : min_conn(2), m_max_conn(5), m_cur_conn(0), m_abort(false) {
}
ConnPool(int maxConn = 5); // 初始化只需设置最大连接数
virtual ~ConnPool();
virtual int init(); // 使用池之前总是初始化这个池
virtual Conn* takeConn(const int timeout_ms = -1); // 从池中拿一个连接
virtual void putConn(Conn* pConn); // 将一个连接返回池中
protected:
virtual Conn* newFreeConn() = 0; // 根据具体的连接库类型去实现
const int min_conn; // 最小备用连接数量
int m_cur_conn; // 当前已创建的连接数量
int m_max_conn; // 最大允许创建连接数量
list<Conn*> m_free_list; // 空闲的连接
list<Conn*> m_busy_list; // 正在被使用的连接
mutex m_mutex;
condition_variable m_cond;
bool m_abort