Mysql数据库连接池的简单实现(基于C++11), 基础学完, 包教包会.

2023-11-20

项目技术点

  1. C语言进行MYSQL数据库编程

  2. 无锁单例

  3. 基于STL队列加C++11新特性保证线程安全实现的生产者消费者模型

  4. C++11多线程编程 (线程间同步与互斥)

  5. 基于CAS的原子整形

  6. lambda表达式

  7. shared_ptr智能指针管理Connection*指针对象

  8. 基于C++11标准库实现, 具备跨平台的特性,省去了对于pthread库的C++的封装.更加针对于项目的核心逻辑上的思考和实现. (主干到细节)

  9. Makefile自动化编译

项目意义

高并发场景下, 频繁创建, 销毁连接带来的性能损耗

三次握手,连接认证(身份权限认证),MySQL资源释放, 四次挥手

每一次client 访问 Mysql server都需要进行上述操作. 上述这些操作是固定的流程. 真正的sql语句执行操作才是我们无法逃脱的, 所以上述这些我们完全可以提前创建出来,然后进行不断的复用connections. 实现mysql server访问的性能提升.

思考: 提前创建好的 connetions 数目是否是越多越好?

当然是不可能,因为每一个connection都是需要占据一定的系统资源的, 创建过多的connection 会导致服务器资源紧张. 起码per connection per socketfd (套接字资源)

思考: connections 数目设计?

上下限限制数目. initSize控制下限. maxSize控制连接上限 (一般是系统的最大mysql connetions num)

多余connection最长闲置时间限制: maxIdleTime (及时释放闲置连接)

资源紧张, 并发访问量高. 没有连接可用 :connectionTimeout (return error, 获取连接超时时间)

项目实现

Connection设计

数据成员

MYSQL* _conn;         //连接句柄                                  
clock_t _startTime;   //连接起始空闲时间

操作接口

Connection();            //构造 init Connection
~Connection();           //析构 destroy connection
bool connect(ip, port, username, password, dbname);     //连接操作, 返回连接结果
bool update(sql);        //表更新操作, 返回更新结果 
MYSQL_RES* query(sql);   //查询操作, 返回查询结果
void refreshStartTime(); //刷新连接起始空闲时间
clock_t getAliveTime();  //获取连接空闲时间

ConnectionPool设计

数据成员

//连接登录信息
string _ip;
unsigned short _port;
string _username;
string _password;
string _dbname;
//连接数量等配置信息
int _initSize;
int _maxSize;
int _maxIdleTime;
int _connectionTimeout;
//连接存储信息,以及保证线程安全
queue<Connection*> _connectionQue;
mutex _queueLock;
condition_variable _cond;
atomic_int _connectionCnt;

操作接口

ConnectionPool();                          //构造 init pool, 加载配置, 初始连接, 启动线程
static ConnectionPool* getConnectionPool();//获取单例
shared_ptr<Connection> getConnection();    //获取连接
int _loadConfigFile(string& filename);     //加载解析配置信息
void produceConnectionTask();              //生产连接任务
void scannerConnetionTask();               //扫描监视销毁空闲线程任务

项目复杂接口细节刨析

getConnection()

/*
    从连接池中获取一条连接. 相当于是消费者
    消费前提, _connectionQue中有货, 所以无货期间需要进行阻塞休眠等待. 
    等待也不能一直等待. 存在连接超时时间, 
    waittime >= _connectionTimeout then output << error.
*/
shared_ptr<Connection> getConnection() {
    unique_lock<mutex> auto_lock(_queueLock);//定义智能锁
    while (_connectionQue.empty()) {
        if (cv_status::timeout == _cond.wait_for(auto_lock,                                          chrono::milliseconds(_connectionTimeout))) { //达到连接超时时间
            if (_connectionQue.empty()) {
                //LOG DEBUG INFO
                cerr << "获取连接超时" << endl;
                return nullptr;
            }
        }
    }
    //定义shared_ptr<Connection> 自定义del函数, 而非直接调用~T()
    shared_ptr<Connection> sp(_connectionQue.front(), [&](Connection* pconn){
        unique_lock<mutex> auto_lock(_queueLock);
        pconn->refreshStartTime();      //刷新连接起始空闲时间
        _connectionQue.push(pconn);
    });
    _connectionQue.pop();
    _cond.notify_all();                 //弹出任务, queue maybe empty notify produce
    return sp;
}

produceConnectionTask()

/*
    生产者线程任务. 在_connectionQue中无connetion 
    && _connectionCnt < _maxSize 时候 及时创建连接填充_connectionQue。                   
*/
void produceConnectionTask() {
    for (;;) {
        unique_lock<mutex> auto_lock(_queueLock);
        while (!_connectionQue.empty()) {
            _cond.wait(auto_lock);
        }
        if (_connectionCnt < _maxSize) {
            Connection* pconn = new Connection();
            pconn->connet(_ip, _port, _username, _password, _dbname);
            pconn->refreshStartTime();
            _connectionQue.push(pconn);
            _connectionCnt++;
        }
        _cond.notify_all(); //通知消费
    }
}
​

scannerConnetionTask()

/*
	不停的扫描所有的connection, 从头到尾的扫描, 
    监控销毁哪些长期空闲的connection, 避免对于空闲资源的无端占用浪费.  
    每一次休眠一个 _maxIdleTime 就出来 检查, 定期轮询检查空闲丽连接进行销毁
*/
void scannerConnectionTask() {
    for (;;) {
        //休眠maxIdleTime
    	this_thread::sleep_for(chrono::seconds(_maxIdleTime));   
        unique_lock<mutex> auto_lock(_queueLock);
        while (_connectionCnt > _initSize)
		{
			Connection *p = _connectionQue.front();
			if (p->getAliveeTime()/SECONDS_PER_SEC >= _maxIdleTime)
			{
				_connectionQue.pop();
				_connectionCnt--;
				delete p; // 调用~Connection()释放连接
			}
			else
			{
				break; // 队头的连接没有超过_maxIdleTime,其它连接肯定没有
			}
		}       
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mysql数据库连接池的简单实现(基于C++11), 基础学完, 包教包会. 的相关文章

随机推荐

  • 亲测有效win10系统QQ音乐无法安装

    本人使用win10专业版时 因为一些原因 多次下载qq音乐都无法进入安装界面 找了很多原因都无法解决 最后在网上找到好像是因为火绒的原因 于是关闭火绒 再次尝试安装 遂成功 实在不行可以卸载火绒安全后重启电脑 再从官网重新下载QQ音乐安装包
  • 数据预处理-独热编码(One-Hot)

    1 部分特征如人的性别有男女 国家有中国 美国 法国等 并不是连续的 而是离散的 无序的 通常我们需要对其进行特征数字化 2 假如某个样本 某个人 他的特征是这样的 男 中国 乒乓球 我们可以用 0 0 4 来表示 但是这样的特征处理并不能
  • BeautifulSoup基本用法总结

    BeautifulSoup是Python的一个库 最主要的功能就是从网页爬取我们需要的数据 BeautifulSoup将html解析为对象进行处理 全部页面转变为字典或者数组 相对于正则表达式的方式 可以大大简化处理过程 0x01 安装 建
  • Leetcode 106. 从中序与后序遍历序列构造二叉树

    文章目录 题目 代码 9 18 首刷自解 题目 Leetcode 106 从中序与后序遍历序列构造二叉树 代码 9 18 首刷自解 class Solution public unordered map
  • UE4文字显示乱码“字字字字字字字字”的解决办法

    键盘win R 搜索fonts 2 滑到最底下右键复制 宋体常规简体字 3 复制到ue4项目的字体文件夹中 如下 注意在外部文件处复制 4 回到项目界面 此时右下角会有个弹窗提示是否确认导入 点击导入 然后会弹一个 字体样式导入选项 弹框
  • openGauss学习笔记-63 openGauss 数据库管理-资源池化架构

    文章目录 openGauss学习笔记 63 openGauss 数据库管理 资源池化架构 openGauss学习笔记 63 openGauss 数据库管理 资源池化架构 本文档主要介绍资源池化架构下的一些最佳实践和使用注意事项 用于支撑对相
  • go Cobra命令行工具入门

    简介 Github https github com spf13 cobra Star 26 5K Cobra是一个用Go语言实现的命令行工具 并且现在正在被很多项目使用 例如 Kubernetes Hugo和Github CLI等 通过使
  • Failed to set locale, defaulting to C.UTF-8解决方法

    CentOS 8Linux系统提示 Failed to set locale defaulting to C UTF 8 这是由于没有配置正确的语言环境导致的 Linux百科 使用root账户登录你的CentOS操作系统 然后执行两条命令
  • 现阶段计算机网络技术专业人才培养的发展对策

    确立具有高职特色的人才培养目标 在市场经济的条件下 人才培养首先要适应市场需求 以市场行业的需求为导 向制定人才培养目标 学校人才培养是否能满足社会需求 可以通过学生在对口行 业及相关领域的就业情况来衡量 高职教育培养高技能应用型人才 与研
  • Objective-C中的封装、继承、多态、分类

    封装 封装最好理解了 封装是面向对象的特征之一 是对象和类概念的主要特性 封装 也就是把客观事物封装成抽象的类 并且类可以把自己的数据和方法只让可信的类或者对象操作 对不可信的进行信息隐藏 继承 面向对象编程 OOP 语言的一个主要功能就是
  • 测试工具73款

    我们将本文的软件测试工具分为4类 1 Web应用测试工具 2 网站安全测试工具 3 跨浏览器测试工具 4 移动应用测试工具 注 工具排名没有任何意义 1 Web应用测试工具 我们列出了一些在Web应用程序上执行性能 负载和压力测试的关键工具
  • 开源项目MiniWord .NET Word 操作由Word模板和数据简单、快速生成文件

    MiniWord NET Word 介绍 MiniWord NET Word模板引擎 藉由Word模板和数据简单 快速生成文件 image Getting Started 安装 nuget link https www nuget org
  • ubuntu18.04命令安装ros2

    ROS2官方文档 本教程为apt get命令安装方式 官网教程有点问题 借鉴一下大佬的安装方式 文章目录 1 安装ROS2 1 1 安装秘钥相关指令 1 2 授权秘钥 1 3 添加ROS2软件源 1 4 安装 2 设置环境 可选但是推荐 2
  • vue路由器学习(个人学习笔记四)

    目录 友情提醒 第一章 路由简介 1 1 什么是路由 1 2 安装路由插件 第二章 自定义路由器 2 1 创建路由器文件index js文件 2 2 index js文件中配置路由信息 第三章 使用路由器 3 1 在main js文件中将路
  • 基于Item的协同过滤算法实践(最简单的在线电影推荐系统)

    上一篇文章 基于用户的协同过滤算法实践 中 基于用户的相似度生成推荐列表 本文将基于Item的相似度阐述 1 相似度 基于物品的协同过滤算法 简称ItemCF 给用户推荐那些和他们之前喜欢的物品相似的物品 不过ItemCF不是利用物品的内容
  • 用户权限数据转换为用户组列表(3/3) - Excel PY公式

    最近Excel圈里的大事情就是微软把PY塞进了Excel单元格 可以作为公式使用 轻松用PY做数据分析 系好安全带 老司机带你玩一把 实例需求 如下是AD用户的列表 每个用户拥有该应用程序的只读或读写权限 现在需要创建新的AD用户组 并根据
  • Source Insight4.0的安装以及配置

    安装source insight4 工具的动机 1 公司需求 2 source insight4 0工具是集开发快速以及界面美观和方便等多种优点于一个软件的编辑器 1 需要准备资料 source insight4 0的安装包 以及安装的过程
  • iOS内存详解

    堆栈 iOS内存条中有一部分是只读的 有一部分是可读可写的 我们操作的是可读可写部分 那么在这块内存当中 我们怎么划分堆和栈呢 我们可以限定死堆栈的内存空间 但是这样显然是不好的 那么可以使用相对弹性的空间 一个从上往下扩展 一个从下往上扩
  • Arthas阿里 阿尔萨斯诊断工具的学习

    以下所有内容基于Arthas的3 6 9版本 一 Arthas 基础 背景 线上诊断问题比较难复现 DEBUG等 都很痛苦 功能好处 通过JVM开放出来接口 代理功能 对JVM访问 获取JVM内存 线程 类 方法 变量等各种操作函数 并控制
  • Mysql数据库连接池的简单实现(基于C++11), 基础学完, 包教包会.

    项目技术点 C语言进行MYSQL数据库编程 无锁单例 基于STL队列加C 11新特性保证线程安全实现的生产者消费者模型 C 11多线程编程 线程间同步与互斥 基于CAS的原子整形 lambda表达式 shared ptr智能指针管理Conn