• 连接池的实现


    1. 背景

    工程架构中有很多访问下游的需求,下游包括但不限于服务/数据库/缓存,其通讯步骤为:

    (1)与下游建立一个连接

    (2)通过这个连接,收发请求

    (3)交互结束,关闭连接,释放资源

    2. 为什么需要连接池?

    当并发量很低的时候,建立连接和关闭连接的过程是没问题的,但当服务单机QPS达到几百、几千的时候,建立连接和销毁连接就会成为瓶颈,此时如何优化?

    结论很简单,服务启动的时候,先建立好若干连接Array[Connection],但有请求过来的时候,从Array中取出一个,执行下游操作,执行完再放回,从而避免反复的建立和销毁连接,以提升性能。

    而这个对Array[Connection]进行维护的数据结构,就是连接池

    3. 连接池核心接口和实现

    通过上面的讨论,可以看到连接池ConnectionPool主要有三个核心接口

    (1)Init:初始化好Array[Connection],这个接口只在服务启动时调用一次;

    (2)GetConnection:请求每次需要访问数据库时,不是connect一个连接,而是通过连接池的这个接口拿连接;

    (3)FreeConnection:请求每次访问完数据库时,不是关闭一个连接,而是把这个连接放回连接池。

    连接池核心数据结构

    (1)连接数据Array[Connection]

    (2)互斥锁数组Array lock[N]

    连接池核心接口实现:

    Init() {
     for i = 1 to N {
      Array Connection [i] = new();
      Array Connection [i]->connect();
      Array lock[i] = 0;
     }
    }
    说明:把所有连接和互斥锁初始化
    
    GetConnection()
     for i = 1 to N {
      if(Array lock[i] == 0) {
       Array lock[i] = 1;
       return Array Connection[i];
       }
     }
    }
    说明:找一个可用的连接,锁住,并返回连接
    
    FreeConnection(c)
     for i = 1 to N {
     if(Array Connection [i] == c) {
       Array lock[i] = 0;
       }
      }
    }
    说明:找到连接,把锁释放

    4. 细节

    (1)如果连接全部被占用,是返回失败,还是让上游等待?

    (2)需要实施连接可用性检测;

    (3)为了让调用方更友好,可能还需要包装一层DAO层,让“连接”对调用方都是黑盒的;

    (4)通过freeArray,connectionMap可以让取连接和放回连接都达到O(1)时间复杂度;

    (5)可以通过hash实现id串行化;

    (6)负载均衡、故障转移、服务自动扩容都可以在这一层实现。

  • 相关阅读:
    业务领域建模Domain Modeling
    用例建模Use Case Modeling
    分析一套源代码的代码规范和风格并讨论如何改进优化代码
    结合工程实践选题调研分析同类软件产品
    如何提高程序员的键盘使用效率
    python知识准备及环境配置
    一张图片在Python操作下的4种玩法(附源码)
    Python中的错误和异常
    当你忘记网站上的密码时怎么办?Python如何快速帮你找回?
    Python最简单的图片爬虫,20行代码带你爬遍整个网站
  • 原文地址:https://www.cnblogs.com/lujiango/p/9650275.html
Copyright © 2020-2023  润新知