Skip to content

Latest commit

 

History

History
43 lines (35 loc) · 2.49 KB

readme.md

File metadata and controls

43 lines (35 loc) · 2.49 KB

This is a ConnectionPool project

连接池

1. 模型:生产者消费者模型

  1. 生产者:生产连接
  2. 消费者: 使用数据库的客户端

2. 控制连接数量的逻辑

  1. 连接池内连接过多
  • 时间戳记录连接的空闲时间,若空闲时间大于指定时长,就销毁掉该连接
  1. 连接池内连接过少
  • 直接新增连接

涉及技术点

  1. 互斥锁、条件变量(由于模型逻辑简单,所以生产者和消费者共用一把互斥锁一个条件变量,不影响线程池逻辑)
  2. 队列:存储数据库连接
  3. 单例模式懒汉模式中注意线程安全问题,要加锁,利用C++11中的static来实现)
    1. 线程池对象作为静态局部变量:生命周期为整个程序周期,在线程池对外的接口static getConnectionPool函数中声明,并且由于C++11特性,该声明只会有一次
    2. 线程池对象作为私有成员
  4. 通过jason来实现数据库连接信息的传递(通过vcpkg包管理jasoncpp库)
  5. 回收线程有两种方式
    1. 函数控制回收: 当使用连接的线程完成时,调用该函数将连接放回队列中
    2. shared_ptr<T>自动回收连接: 将回收连接的逻辑写在共享指针的删除器

架构图

架构图

性能分析

插入5000条数据

使用连接池 不使用连接池
单线程 33673ms 51257ms
多线程 10302ms 47423ms

可以看到,使用连接池是有显著的性能提升的,并且在多线程+连接池的情况下性能最优

还可以注意到,单线程+使用连接池性能甚至性能比多线程+不使用连接池性能要高,所以,在日常开发中,不是简单的使用多线程就可以最大化优化性能,往往需要搭配其他优化手段才能突破瓶颈

开发中获得的经验

  1. 在多线程+不使用连接池的情况下,会出现插入丢失,这是因为多个线程同时登陆mysql,mysql会拒绝某些连接,这时需要在开启多线程之前,预连接数据即可
  2. 修改数据库编码格式要使用utf8而不是utf-8
  3. 在遇到程序bug时,不要直接用gdb去debug,要先用DBMS测试一下数据库是否能连接上,不然的话直接去debug花费大量时间在其他地方最后才发现是数据库没连接上。
  4. 在wsl中使用mysql,记得要关闭数据库在关机!(不然下次数据库坏了哭都来不及)