谈谈连接池概念原理及使用方面的看法

1. 连接池介绍

        关于“池“,我们可能遇到连接池、进程池等,池的原理都是相近的,连接池比如有数据库连接池、Redis连接池。我们以数据库连接池(Connection pool)为例,讲解一下连接池原理。

为什么要使用连接池?

       传统的数据库连接,没有使用连接池,客户端连接到数据库服务器,每连接一次就建立一个连接,如果在客户端访问量大的时候,数据库服务器建立的连接数持续增长,数据库的可用最大连接数是预先设置好的,比如一次访问上万、上千万的连接,那么数据库服务器的连接数被打满,每个连接都是一个线程,本身每个线程都要耗费服务器的CPU、内存资源,数据库服务器的CPU会处理这些连接线程切换,负载压力就会非常大,连接用完也没有得到及时的释放,那么数据库服务器就会被压垮。实际上,请求次数可以分为请求数、并发数,多数情况请求数远大于并发数,并不是每个访问请求都要建立一个新的连接,也并不是每个请求都要有效连接并使用连接进行数据库相关操作,有些连接可能空耗了资源没有得到充分有效的利用。创建连接是系统耗时操作、还要消耗CPU和内存的线程,如果能重用连接,有效的管理连接资源的使用、释放,保持一定的连接数,充分提高连接的利用率,降低服务器资源消耗,使系统压力减轻。这样的背景原因下,我们自然就有了连接池的概念。

如何解决

       如果有连接池就不同了,如并发100个请求,实际上并不是每个请求的所有时间都在执行SQL查询。这样100个请求,共享20个数据库MySQL连接就可以满足需求了。当一个请求操作完数据库后,开始进入模板渲染等流程,这时就会释放数据库连接给其他的请求使用。

       数据库连接池是我们编写的一个程序组件,组件启动时可以预先建立一定数量的数据库的连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放

适用场景

       连接池仅在出现高并发的应用中才有价值,连接池并没有提高sql的查询速度,连接池是用来保护数据库的,不是用来提升性能的。

      当并发请求QPS达到数万或者数十万时,MySQL服务器就需要维持十万级的连接。这时数据库的压力就会非常大了。连接池技术就可以派上用场了,可以大大降低数据库连接数,减入服务器压力。

注意点

      可能有些人认为使用连接池可以提高性能,其实不然,连接池并不能直接的提高性能,在访问量不大,低并发情况下,不会对性能提升,在访问量大、高并发情况下,可以降低服务器资源消耗,间接的提升性能。

2. 连接池机制原理

       数据的连接池为维持若干个长连接,当新请求到达的时候,如果连接池空闲连接,就分配给连接池去处理,否则,后面的数据库连接请求将被加入到等待队列中。

数据库连接池的机制

(1)  程序初始化时创建连接池;
(2)  使用时向连接池申请可用连接;
(3)  使用完毕,将连接返还给连接池;
(4)  程序退出时,断开连接,并释放资源;

 

数据库连接池设计

1、创建连接:连接池启动后,初始化一定的空闲连接,指定为最少的连接min。当连接池为空,不够用时,创建新的连接放到池里,但不能超过指定的最大连接max数量。

2、连接释放:每次使用完连接,一定要调用释放方法,把连接放回池中,给其他程序或请求使用。

3、连接分配:连接池中用pop和push的方式对等入队和出队分配与回收。能实现阻塞分配,也就是在池空并且已创建数量大于max,阻塞一定时间等待其他请求的连接释放,超时则返回null。

4、连接管理:对连接池中的连接,定时检活和释放空闲连接等。

3.连接池实现

下面是一个连接池的代码。

class pool{
    protected  $maxConnection=10; //最大连接
    protected  $minConnection=5; //最小连接
    protected  $currentConnection; //当前正在使用的连接
    protected  $channel; //存放连接的对象
    protected  $timeout=3; //等待连接的时间
    private static $instance;
    private function __construct ()   {
    }
    public static function  get_instance(){
        if(is_null (self::$instance)){
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function  init(){
         $this->channel=new \Swoole\Coroutine\Channel($this->maxConnection);
         for ($i=0;$i<$this->minConnection;$i++){
             $connection=$this->createConnection();
             $this->channel->push($connection);
             $this->currentConnection++;
         }
    }

    /**
     * 创建连接
     */
    public function  createConnection(){
        try{
            //$swoole_mysql = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'Peter123!');
            $swoole_mysql = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root654321');
        }catch (\Exception $e){
            var_dump($e->getMessage());
        }
        return $swoole_mysql;

    }

    /**
     * 获取连接
     */
    public function  getConnection(){
        $obj=null;
        //1.如果连接不够要添加,判断是否超过最大的连接数,
        if($this->channel->isEmpty()){
              if($this->currentConnection<$this->maxConnection){
                  $obj=$this->createConnection();
                  //$this->channel->push($obj);
                  $this->currentConnection++;
              }else{
                  var_dump("等待获取连接");
                  $obj=$this->channel->pop($this->timeout); //等待其它协程归还连接
              }
        }else{
            $obj=$this->channel->pop($this->timeout); //超时
        }
        //2.如果连接超过要等待
        return $obj;
    }

    /**
     * 释放连接(重新回到连接池)
     */
    public function  freeConnection($obj){
        $this->channel->push($obj);

    }


}

持续完善、待续...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云焰

你的鼓励是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值