数据库连接池(C++11实现)

2023-10-29

目的:

        因为对数据库的操作实质上是对磁盘的IO操作,所以如果对数据库访问次数过多,就会到导致大量的磁盘IO,为了提高MySQL数据库(基于C/S设计)的访问瓶颈,除了在服务器端增加缓存服务器缓存常用的数据 之外(例如Redis),还可以增加连接池,来提高MySQL Server的访问效率。

        在高并发情况下,大量的 TCP三次握手、MySQL Server连接认证、MySQL Server关闭连接回收资源和TCP四次挥手所耗费的时间也十分明显,增加连接池就是为了减少这一部分的性能损耗。

        在系统启动时就创建一定数量的连接,用户一旦执行CURD操作,直接拿出一条连接即可,不需要TCP的连接过程和资源回收过程,使用完该连接后归还给连接池的连接队列,供之后使用。

功能介绍:

 1、初始连接数(initSize):
        初始连接量表示连接池事先会和MySQL Server创建的initSize数量的SqlConn连接。在完成初始连接量之后,当应用发起MySQL访问时,不用创建新的MySQLServer连接,而是从连接池中直接获取一个连接,当使用完成后,再把连接归还到连接池中。
2、最大容量(maxCapacity)
        连接池的最大容量即连接池内的最大连接数。当并发访问MySQL Server的请求增多时,初始连接量不够使用时,会根据新的请求数量去创建更多的连接给应用去使用,但是新创建的连接数量上限是maxCapacity,不能无限制的创建连接,因为每一个连接都会占用一个socket资源,一般连接池和服务器程序是部署在一台 主机上的,如果连接池占用过多的socket资源,那么服务器就不能接收太多的客户端请求了。当这些连接使用完成后,会再次归还到连接池当中来维护。
3、最大空闲时间(maxIdleTime)
        当高并发过去,因为高并发而新创建的连接在很长时间(maxIdleTime)内没有得到使用,那么这些新创建的连接处于空闲状态,并且占用着一定的资源,这个时候就需要将其释放掉,最终只用保存initSize个连接就行。
4、连接超时时间(connTimeOut)
        当MySQL的并发访问请求量过大,连接池中的连接数量已经达到了maxSize,并且此时连接池中没有可以使用的连接,那么此时应阻塞connTimeOut的时间,如果此时间内有使用完的连接归还到连接池,那么就可以使用,如果超过这个时间还是没有连接,那么获取数据库连接就失败,无法访问数据库。

运行流程:

1、使用单例模式(局部静态变量方法)获取连接池实例。

SqlConnPool* pool = SqlConnPool::getInstance();

2、从SqlConnPool中获取和Mysql的连接SqlConn,为了实现RAII的目标,将getConn()函数的返回值设置为shared_ptr<SqlConn>类型。

shared_ptr<SqlConn> sp = pool->getConn();

3、利用获取的连接,对数据库进行CURD操作。

sp->update(sql);
sp->query(sql);

SqlConn类结构         SqlConn.h

#ifndef SQLCONN_H
#define SQLCONN_H

#include <mysql/mysql.h>
#include <chrono>
#include <string>

class SqlConn
{
public:
	SqlConn();
	~SqlConn();
	//建立Sql连接
	bool connect(const std::string& ip,
				 const uint16_t port, 
				 const std::string& user, 
				 const std::string& pwd,
                 const std::string& dbName);

	// 更新操作 insert、delete、update
	bool update(const std::string& sql);
	// 查询操作 select
	MYSQL_RES* query(const std::string& sql);
    //刷新存活时间
	void refreshAliveTime()
	{
		aliveTime = std::chrono::steady_clock::now();
	}
    //获取存活时间间隔
	size_t getAliveTime()
	{
		return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - aliveTime).count();
	}
private:
	MYSQL* conn;//数据库连接
	std::chrono::time_point<std::chrono::steady_clock> aliveTime; //连接存活时间
};

#endif // !SQLCONN_H

Sqlconn实现        Sqlconn.cpp

#include "sqlconn.h"

SqlConn::SqlConn()
{
    conn=mysql_init(nullptr);
    mysql_set_character_set(conn, "utf8");
}

SqlConn::~SqlConn()
{
    if(conn!=nullptr)
    {
        mysql_close(conn);
    }
}

bool SqlConn::connect(const std::string& ip,const uint16_t port,const std::string& user,const std::string& pwd,const std::string& dbName)
{
    MYSQL* ptr=mysql_real_connect(conn,ip.c_str(),user.c_str(),pwd.c_str(),dbName.c_str(),port,nullptr,0);
    return ptr!=nullptr;
}

bool SqlConn::update(const std::string& sql)
{
    if(mysql_query(conn,sql.c_str()))
    {
        return false;       
    }
    return true;
}

MYSQL_RES* SqlConn::query(const std::string& sql) 
{
    if(mysql_query(conn, sql.c_str())) 
    {
        return nullptr;
    }
    return mysql_use_result(conn);
}

注:mysql_query()函数有两种返回值,如果执行的是更新操作(insert、delete、update),则返回 true/ false;如果执行的是查询操作(select),则返回 MYSQL_RES* 类型。
 

SqlConnPool类结构         SqlConnPool.h

#ifndef SQLCONNPOOL_H
#define SQLCONNPOOL_H

#include <mysql/mysql.h>
#include <memory>
#include <string>
#include "sqlconn.h"
#include "blockqueue.h"
#include "log.h"

class SqlConnPool
{
public:
    static SqlConnPool* getInstance(int maxCapacity=1024)
    {
        static SqlConnPool single(maxCapacity);
        return &single;
    }
    std::shared_ptr<SqlConn> getConn();
    
private:
    SqlConnPool(int maxCapacity);
    ~SqlConnPool(){};
    SqlConnPool(const SqlConnPool& other)=delete;
    SqlConnPool& operator =(const SqlConnPool& other)=delete;
    //加载配置文件
    bool loadConfigFile();
    //专门用于产生新连接的线程
    void produceConnTask();
    //扫描超过最大空闲时间maxIdleTime的连接,对其进行回收
    void scannerConnTask();
    //添加新连接
    void addConn();

    std::string ip;
    uint16_t port;
    std::string user;
    std::string pwd;
    std::string dbName;

    size_t initSize;//初始连接数
    size_t maxIdleTime;//最大空闲时间
    size_t connTimeout;//超时时间

    BlockQueue<SqlConn*> connQue;
};

#endif // !SQLCONNPOOL_H

SqlConnPool实现        SqlConnPool.cpp

#include "sqlconnpool.h"
#include <functional>
using std::string;

bool SqlConnPool::loadConfigFile()//加载mysql.ini配置文件
{
    FILE* fp = fopen("./mysql.ini", "r");
    if (fp == nullptr)
    {
        LOG_ERROR("%s","mysql.ini file dose not exsit!");
        return false;
    }    
    while(!feof(fp)) //循环读取配置文件的每一行
    {
    	char line[1024] = {0};
        fgets(line, 1024, fp);
        string str = line;
        int idx = str.find('=', 0);
        if (idx == -1)
        {
            continue;
        }
        int endidx = str.find('\n', idx);
        string key = str.substr(0, idx);//截取key
        string value = str.substr(idx+1,endidx-idx-1);//截取value

        if (key == "ip")    
            ip = value;
        else if (key == "port")
            port = stoi(value);
        else if (key == "username")
            user = value;
        else if (key == "password") 
            pwd = value;
        else if (key == "dbName")
            dbName = value;
        else if (key == "initSize")
            initSize = stoi(value);
        else if (key == "maxIdleTime")
			maxIdleTime = stoi(value);
		else if (key == "connTimeOut")
			connTimeout = stoi(value);
    }
    fclose(fp);
    return true;
}

 void SqlConnPool::addConn()//添加Sql连接
 {
    SqlConn* conn=new SqlConn();
    conn->connect(ip,port,user,pwd,dbName);
    conn->refreshAliveTime();
    connQue.push_back(conn);
 }

//构造SqlConnPool,初始化connQue变量
SqlConnPool::SqlConnPool(int maxCapacity):connQue(maxCapacity)
{
    if (!loadConfigFile())//配置失败
    {
        return ;
    }
    for (size_t i = 0; i < initSize; i++)//添加初始initSize数量的连接
    {
        addConn();
    }
    //初始化日志系统(默认为异步模式)
    Log::getInstance()->init();
    //生产者线程
    std::thread produce(std::bind(&SqlConnPool::produceConnTask, this));
    produce.detach();
    //扫描线程
    std::thread scanner(std::bind(&SqlConnPool::scannerConnTask, this));
    scanner.detach();
}

void SqlConnPool::produceConnTask()
{
    for(;;)
    {
        addConn();
    }
}

void SqlConnPool::scannerConnTask()
{
    for (;;)
    {
        std::this_thread::sleep_for(std::chrono::microseconds(maxIdleTime));
        while (connQue.get_size() > initSize)//清除超出最大空闲时间的连接
        {
            SqlConn* p = connQue.front();
            if(p->getAliveTime() >= maxIdleTime)
            {
                SqlConn* tmp=nullptr;
                connQue.pop(tmp);
                delete tmp;
            }
            else 
                break;
        }
    }
}

std::shared_ptr<SqlConn> SqlConnPool::getConn()//获取一个Sql连接
{
    SqlConn* conn;
    if (!connQue.pop(conn,connTimeout))//超过连接超时时间
    {
        LOG_ERROR("%s","get connection timeout");
        return nullptr;
    }
   std::shared_ptr<SqlConn> sp(conn,
          [&](SqlConn* p) 
          {
              p->refreshAliveTime();
              connQue.push_back(p);
          });//自定义删除函数(删除时将连接再次放入阻塞队列中,重复使用)
    return sp;
}

测试程序        testSqlConnPool.cpp

四种试验:多线程无连接池、多线程有连接池、单线程无连接池、单线程有连接池

分别测试其“建立10000个数据库连接,每个连接执行一次插入语句”的运行时间。

#include "sqlconn.h"
#include "sqlconnpool.h"
#include <time.h>
#include <iostream>
using namespace std;

void SigleWithConnection()//单线程有连接池
{
	time_t begin = clock();
	for (int i = 0; i < 10000; ++i)
	{
		SqlConnPool* pool = SqlConnPool::getInstance();

		shared_ptr<SqlConn> sp = pool->getConn();
		char sql[1024] = {0};
		sprintf(sql, "insert into user(username,password) values('%s','%s')","zhangsan","123456");
		sp->update(sql);
	}
	time_t end = clock();
	cout << (end - begin)/1000 << " ms" << endl;
}

void SigleNoConnection()//单线程无连接池
{
	time_t begin = clock();
	for (int i = 0; i < 10000; ++i)
	{
		SqlConn conn;
		char sql[1024] = {0};
		sprintf(sql, "insert into user(username,password) values('%s','%s')","zhangsan","123456");
		conn.connect("127.0.0.1", 3306, "root", "123456", "yourdb");
		conn.update(sql);
	}
	time_t end = clock();
	cout << (end - begin)/1000 << " ms" << endl;
}


void runInThreadNoConn()
{   
    for (int i = 0; i < 2500; ++i)
		{
			SqlConn conn;
			char sql[1024] = { 0 };
			sprintf(sql, "insert into user(username,password) values('%s','%s')","zhangsan","123456");
			conn.connect("127.0.0.1", 3306, "root", "123456", "yourdb");
			conn.update(sql);
		}
}

void MutiNoConnection()//多线程无连接池
{
	SqlConn conn;
	conn.connect("127.0.0.1", 3306, "root", "123456", "yourdb");
	time_t begin = clock();
	for(int i=0;i<4;i++)
    {
        thread t=thread(runInThreadNoConn);
        t.join();     
    }
	time_t end = clock();
	cout << (end - begin)/1000 << " ms" << endl;
}

void runInThreadByConn()
{   
    for (int i = 0; i < 2500; i++)
	{
		SqlConnPool* pool = SqlConnPool::getInstance();
        shared_ptr<SqlConn> sp = pool->getConn();
		char sql[1024] = {0};
		sprintf(sql, "insert into user(username,password) values('%s','%s')","zhangsan","123456");
		if (sp == nullptr)
		{
			cout << "sp is empty" << endl;
			continue;
		}
		sp->update(sql);
	}
}

void MutiWithConnection()//多线程有连接池
{
	time_t begin = clock();
	for(int i=0;i<4;i++)
    {
        thread t=thread(runInThreadByConn);
        t.join();     
    }
	time_t end = clock();
	cout << (end - begin)/1000 << " ms" << endl;
}

int main()
{ 
	MutiNoConnection();//多线程无连接池
	MutiWithConnection();//多线程有连接池
	SigleNoConnection();//单线程无连接池
	SigleWithConnection();//单线程有连接池
	return 0;
}

测试结果

 由结果可知,使用多线程+连接池的组合有效提高了数据库的访问效率。

  • 数据量10000,单线程从5280ms变成2080ms
  • 数据量10000,多线程从2140ms变成了1910ms

附:

配置文件        mysql.ini

# 数据库连接池配置文件
ip=127.0.0.1
port=3306
username=root
password=123456
dbName=yourdb
#初始连接数
initSize=4
# 最大空闲时间,单位ms
maxIdleTime=6000
# 连接超时时间,单位ms
connTimeOut=100

Makefile

CXX = g++
CFLAGS = -std=c++14 -O2 -Wall -g 

TARGET = testSqlConnPool
OBJS =  buffer.cpp log.cpp blockqueue.h\
		sqlconn.cpp sqlconnpool.cpp\
        testSqlConnPool.cpp

all: $(OBJS)
	$(CXX) $(CFLAGS) $(OBJS) -o $(TARGET)  -pthread -L/usr/lib64/mysql -lmysqlclient

clean:
	rm -rf $(OBJS) $(TARGET)

阻塞队列实现

基于C++11实现的阻塞队列(BlockQueue)_{(sunburst)}的博客-CSDN博客

删去代码中的LOG_XXXX语句,就无需链接 log.cpp,且无需链接仅与日志系统有关的 buffer.cpp 

日志系统实现

同步+异步日志系统(C++实现)_{(sunburst)}的博客-CSDN博客

缓冲区实现

缓冲区Buffer类的设计(参考Muduo实现)_{(sunburst)}的博客-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据库连接池(C++11实现) 的相关文章

  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 在 MySQL 中使用 COUNT 时如何返回 0 而不是 null

    我使用此查询返回存储在 sTable 中的歌曲列表以及存储在 sTable2 中的总项目数 SQL queries Get data to display sQuery SELECT SQL CALC FOUND ROWS str repl
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐

  • 【经典】SpringBoot自定义配置信息

    当我们系统中为方便管理 会定义一些自定义配置项 方便系统的管理和维护 在SpringBoot中 有两种方式可以进行自定义配置 Value 进行单个属性的注入 ConfigurationProperties 类型安全加载 Value方式注入
  • C语言取出一个长整型数中的偶数并构成一个新数案例讲解

    思路分析 1 本题的难点在于 如何把一个长整型数中每一位上的数依次取出 可以使用while循环对整数中的每一位进行取模操作 取出最后一位数 然后把这个数保存到一个数组中 并用除法去掉最后一位数 循环遍历直到一个整数中的每一位都被取出并依次保
  • GitKraken中push时,报ssh key的错误

    问题 configured ssh key is in an invalid format please ensure that your key is valid and is an rsa type key 解决方案 1 GitKrak
  • 卓越性能代码_Win10如何开启卓越模式?学会输入这串代码,电脑性能大幅提升...

    自己的电脑性能如何总是被用户所关注的 那么今天就是来给大家介绍一个Win10的模式 输入一串代码后即可开启该模式 卓越模式 该模式开启之后 完全可以用来代替 高性能 模式 尤其是对于喜欢超频 玩硬件的用户来说还是比较推荐使用的 比较该模式下
  • 新手如何在IEEE上发表论文?

    IEEE 也就是美国电子与电器工程师学 Institute of Electrical and Electronics Engineers 是一个国际性的电子技术与信息科学工程师的学术组织 其会员人数超过40万人 遍布160多个国家 是世界
  • Spring Boot配置MySQL多数据源

    1 导读 在日常开发中我们都是以单个数据库进行开发 在小型项目中是完全能够满足需求的 但是 当我们牵扯到像淘宝 京东这样的大型项目的时候 单个数据库就难以承受用户的CRUD操作 那么此时 我们就需要使用多个数据源进行读写分离的操作 这种方式
  • 最快速度求两个数组之交集算法与hash

    一个题目 该题目来自58同城的二面 用最快速度求两个数组之交集算法 比如A 6 2 4 1 B 2 9 4 3 那么A B 2 4 算法一 在大多数情况 也就是一般的情况下 大家都能想出最暴力的解法 通常也就是采用遍历或者枚举的办法来解决问
  • SpringBoot使用log

    目录 简介 实现步骤 1 在 pom xml 文件中添加 lombak 依赖 2 配置 application properties 日志设置 3 在要使用日志的类上直接添加 Slf4j 注解 然后就可以直接使用 log xxx 方法记录日
  • ABAP对excel的操作(为单元格设置公式)

    文章目录 前言 一 效果 二 代码 前言 给单元格设置公式 一 效果 运行程序 执行 excel效果 二 代码 代码如下 示例 Report ZDEMO EXCEL6
  • 编程职业的乐趣

    编程职业的乐趣 美酒的酿造需要年头 美食的烹饪需要时间 片刻等待 更多美味 更多享受 Good cooking takes time If you are made to wait it s to serve you better and
  • C语言 创建简单结构体输入学生基本信息

    结构体 include
  • VM虚拟机怎么安装mac os?(全教程)

    网络上教程很多 大多数是缺这缺那的 基本上不完整的 我试了很多次看了好多文档才安装成功 现在把我安装成功的过程写下来让更多的人知道如何在windows虚拟机上安装苹果的Mac os 让大家避免走不需要走的路 保姆级教程 此方法我在三台不同配
  • 使用支持向量机进行航线预测————附Matlab代码

    使用支持向量机进行航线预测 附Matlab代码 随着交通运输的发展 航空公司需要提高飞行的效率和安全性 而飞行航线的规划是保证飞行效率和安全性的关键因素之一 因此 利用机器学习算法来预测航线 成为了一个热门的话题 其中 支持向量机 Supp
  • 绕过圆括号过滤实现XSS弹框

    用data协议
  • 思科实验9.网络层:PPP协议配置

    PPP协议配置 基础知识 常用命令 实验流程 目的 1 设计拓扑 2 配置主机IP地址 3 配置路由器 4 设置PPP协议 5 验证主机连通 基础知识 PPP协议即点对点协议 是在点对点连接上传输多协议数据包提供了一个标准方法 是一种点到点
  • 算法进阶指南:0x18:双栈排序

    Tom 最近在研究一个有趣的排序问题 通过 2 个栈 S1 和 S2 Tom 希望借助以下 4 种操作实现将输入序列升序排序 操作 a 如果输入序列不为空 将第一个元素压入栈 S1 操作 b 如果栈 S1 不为空 将 S1 栈顶元素弹出至输
  • uboot下内存操作mw和md命令详解

    mw简介 u boot 中的 mw 命令是用于向内存写入数据的命令 它有4种形式 mw b 写入 1 个字节 8 比特 的数据 mw w 写入 1 个字 2 字节 16 比特 的数据 mw l 写入 1 个长字 4 字节 32 比特 的数据
  • Redis 学习笔记2:redis.conf配置文件详解

    Redis 的配置文件位于 Redis 安装目录下 文件名为 redis conf 参数说明 参数说明 redis conf 配置项说明如下 1 Redis默认不是以守护进程的方式运行 可以通过该配置项修改 使用yes启用守护进程 daem
  • 阻抗匹配之反射波形测量

    稍微接触过高速信号的朋友 一定对阻抗匹配和信号反射都有所了解 甚至可以按照公式 把反射波形一路推导出来 但是 纸上得来终绝浅 绝知此事要躬行 今天 我们就来实测一下信号反射波形 测试环境如下 信号发生器产生一个1 25MHz VPP 2V的
  • 数据库连接池(C++11实现)

    目的 因为对数据库的操作实质上是对磁盘的IO操作 所以如果对数据库访问次数过多 就会到导致大量的磁盘IO 为了提高MySQL数据库 基于C S设计 的访问瓶颈 除了在服务器端增加缓存服务器缓存常用的数据 之外 例如Redis 还可以增加连接