C++手撕连接池-创新互联-成都快上网建站

C++手撕连接池-创新互联

用c++写一个数据库连接池

创新互联是专业的高密网站建设公司,高密接单;提供成都网站制作、成都网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行高密网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!

数据库连接池是为了提高数据库连接的性能,进行连接复用

对于复杂数据库进行大量引用的场景下就会出现访问瓶颈

常见的两种解决方法就是:为了减少磁盘 I/O的次数,在数据库和服务器的应用中间加一层 缓存数据库(例如:Redis、Memcache);
或者就是增加连接池,来减少高并发情况下大量 TCP三次握手、MySQL Server连接认证、MySQL Server关闭连接回收资源和TCP四次挥手 所耗费的性能。

机制解读:

连接池呢就是为数据库连接建立一个缓冲池。
1:从连接池获取或创建可用连接
2:使用完毕之后,把连接返回给连接池
3:在系统关闭前,断开所有连接并释放连接占用的系统资源
4:能够处理无效连接,限制连接池中的连接总数不低于或者不超过某个限定值

池子里四个基本属性:

初始连接量(init_size): 表示连接池事先会和MySQL服务器创建init_size个connection连接,当应用发起MySQL访问时,不用再创建和MySQL服务器新的连接,直接从连接池中获取一个可用的连接就可以,使用完成后,并不去释放connection,而是把当前connection再归还到连接池当中。

大连接(max_size): 当并发访问MySQL服务器的请求增多时,初始连接量已经不够使用了,此时会根据新的请求数量去创建更多的连接给应用去使用,但是新创建的连接数量上限是max_size,不能无限制的创建连接。因为每个连接都会占用一个socket资源,一般连接池和服务器程序是部署在一台主机上的,如果连接池占用过多的socket资源,那么服务器就不能接收更多的客户端请求了。当这些连接使用完成后,再次归还到连接池当中来维护。

大空闲时间(max_idle_time): 当访问MySQL的并发请求多了以后,连接池里面的连接数量会动态增加,上限是max_size个,当这些连接用完再次归还到连接池当中。如果在指定的max_idle_time里面,这些新增加的连接都没有被再次使用过,那么新增加的这些连接资源就要被回收,只需要保持初始连接量init_size个连接就可以了。

连接超时时间(connection_timeout): 当MySQL的并发请求量过大,连接池中的连接数量已经到达max_size了,而此时没有空闲的连接可供使用,那么此时应用无法从连接池获取连接,它通过阻塞的方式等待获取连接的时间如果超过connection_timeout时间,那么连接失败,无法访问数据库。

技术点的分析:

通过预先创建一定数量的连接,放到一个池子。当客户端有请求时,服务器端需要与mysql进行交互,那么只需要从池子里取出一个连接,当操作完成再将连接放到连接池中。如此以来避免了频繁的创建和销毁线程。

1.池子只需要一个就够用了,一个池子里有很多连接了。所以对于线程池这个类而言使用单例模式最为合适。用c++11内部静态变量这种线程安全的方法做的

2.池子里面连接存在类似队列这种容器里面,直接用queue了,每次新的连接从队尾进去,队头的连接用完之后,如果空闲太久,占资源就需要把他销毁掉

3.进行数据库连接的话需要mysql相关的api,用c++的话,就把这些api封装一下,具体常用的api之前有写过一篇博客 C/C++链接mysql_

这封装成一个数据库连接类,里面就是伴随着数据库的初始化,查询,更新,事务的一系列操作。连接池里面队列放的就是这一个个数据库连接的类对象

4.需要访问数据库的线程从连接池里面取出连接,和给池子里添加新连接的线程构成了一个典型的生产者消费者,用条件变量加+互斥锁保证同步,cas原子操作 定义一个连接池内的连接数量,用来当做我们生产和消费线程工作都要参考的变量,变量必须保证其原子性

5.对于获取连接池中的连接来说,用户只需要关心使用,去连接池里直接获取连接并且使用即可,并不用关心连接的生成和销毁,并且,对于使用完的连接来说,为了达到复用的目的,我们并不希望把它释放掉,而是使用完之后将其放回到连接池中供其他消费者使用,这个我们就可以使用智能指针来完成用lambda表达式定制连接释放的功能,(把连接重新还给池子);重新放进连接池呢就是重新push到队列池子里,不过要更新一下时间戳,记录每个连接的存活时间

6.连接池实现自动管理连接数(不够时创建连接,销毁空闲时间较长的连接)

需要通过两个子线程,因为主线程不能阻塞在这个地方,所以通过两个子线程取完成,设置线程分离

一个子线程用来不够时自动创建连接:

  线程池维护了两个数据,一个最小连接数,一个大连接数

一个子线程用来销毁空闲时间较长的连接:

  大概实现思路:从队头取出连接,并将该连接的空闲时长与设定的大空闲时长比较,如果大于等于就从队列中弹出并销毁

7.利用Jsoncpp库去解析json文件,配置环境

整个流程原理大概就这样

当时做了四组压力测试:

一个线程去连接数据库每次插一条数据,测试5000下

用连接池省了和数据库建立连接的损耗 

多线程的话,测了五个线程(好比五个用户)不断的去同时连接数据库,每次连接插入一条数据,一共插5000条

接上连接池,效率更高

测了5000条数据,能很明显的看到单线程多线程下使用连接池,访问速度有着明显的提高

总结:深入了解了池化的技术,可以和线程池配套,作为一个不错的项目

源码放在这了:Xw-oorik

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页名称:C++手撕连接池-创新互联
网站网址:http://kswjz.com/article/hhhoc.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流