今天在写zabbix storm job监控脚本的时候用到了python的redis模块,之前也有用过,但是没有过多的了解,今天看了下相关的api和源码,看到有ConnectionPool的实现,这里简单说下。
在ConnectionPool之前,如果需要连接redis,我都是用StrictRedis这个类,在源码中可以看到这个类的具体解释:

redis.StrictRedis Implementation of the Redis protocol.This abstract class provides a Python interface to all Redis commands and an
implementation of the Redis protocol.Connection and Pipeline derive from this, implementing how the commands are sent and received to the Redis server

使用的方法:

 r=redis.StrictRedis(host=xxxx, port=xxxx, db=xxxx)r.xxxx()

有了ConnectionPool这个类之后,可以使用如下方法

pool = redis.ConnectionPool(host=xxx, port=xxx, db=xxxx)
r = redis.Redis(connection_pool=pool)

这里Redis是StrictRedis的子类
简单分析如下:
在StrictRedis类的__init__方法中,可以初始化connection_pool这个参数,其对应的是一个ConnectionPool的对象:

class StrictRedis(object):
........def __init__(self, host='localhost', port=6379,db=0, password=None, socket_timeout=None,socket_connect_timeout=None,socket_keepalive=None, socket_keepalive_options=None,connection_pool=None, unix_socket_path=None,encoding='utf-8', encoding_errors='strict',charset=None, errors=None,decode_responses=False, retry_on_timeout=False,ssl=False, ssl_keyfile=None, ssl_certfile=None,ssl_cert_reqs=None, ssl_ca_certs=None):if not connection_pool:..........connection_pool = ConnectionPool(**kwargs)self.connection_pool = connection_pool

在StrictRedis的实例执行具体的命令时会调用execute_command方法,这里可以看到具体实现是从连接池中获取一个具体的连接,然后执行命令,完成后释放连接:

   # COMMAND EXECUTION AND PROTOCOL PARSINGdef execute_command(self, *args, **options):"Execute a command and return a parsed response"pool = self.connection_poolcommand_name = args[0]connection = pool.get_connection(command_name, **options)  #调用ConnectionPool.get_connection方法获取一个连接try:connection.send_command(*args)  #命令执行,这里为Connection.send_commandreturn self.parse_response(connection, command_name, **options)except (ConnectionError, TimeoutError) as e:connection.disconnect()if not connection.retry_on_timeout and isinstance(e, TimeoutError):raiseconnection.send_command(*args)  return self.parse_response(connection, command_name, **options)finally:pool.release(connection)  #调用ConnectionPool.release释放连接

在来看看ConnectionPool类:

     class ConnectionPool(object):  ...........def __init__(self, connection_class=Connection, max_connections=None,**connection_kwargs):   #类初始化时调用构造函数max_connections = max_connections or 2 ** 31if not isinstance(max_connections, (int, long)) or max_connections < 0:  #判断输入的max_connections是否合法raise ValueError('"max_connections" must be a positive integer')self.connection_class = connection_class  #设置对应的参数self.connection_kwargs = connection_kwargsself.max_connections = max_connectionsself.reset()  #初始化ConnectionPool 时的reset操作def reset(self):self.pid = os.getpid()self._created_connections = 0  #已经创建的连接的计数器self._available_connections = []   #声明一个空的数组,用来存放可用的连接self._in_use_connections = set()  #声明一个空的集合,用来存放已经在用的连接self._check_lock = threading.Lock()
.......def get_connection(self, command_name, *keys, **options):  #在连接池中获取连接的方法"Get a connection from the pool"self._checkpid()try:connection = self._available_connections.pop()  #获取并删除代表连接的元素,在第一次获取connectiong时,因为_available_connections是一个空的数组,会直接调用make_connection方法except IndexError:connection = self.make_connection()self._in_use_connections.add(connection)   #向代表正在使用的连接的集合中添加元素return connection   def make_connection(self): #在_available_connections数组为空时获取连接调用的方法"Create a new connection"if self._created_connections >= self.max_connections:   #判断创建的连接是否已经达到最大限制,max_connections可以通过参数初始化raise ConnectionError("Too many connections")self._created_connections += 1   #把代表已经创建的连接的数值+1return self.connection_class(**self.connection_kwargs)     #返回有效的连接,默认为Connection(**self.connection_kwargs)def release(self, connection):  #释放连接,链接并没有断开,只是存在链接池中"Releases the connection back to the pool"self._checkpid()if connection.pid != self.pid:returnself._in_use_connections.remove(connection)   #从集合中删除元素self._available_connections.append(connection) #并添加到_available_connections 的数组中def disconnect(self): #断开所有连接池中的链接"Disconnects all connections in the pool"all_conns = chain(self._available_connections,self._in_use_connections)for connection in all_conns:connection.disconnect()

execute_command最终调用的是Connection.send_command方法,关闭链接为 Connection.disconnect方法,而Connection类的实现:

class Connection(object):"Manages TCP communication to and from a Redis server"def __del__(self):   #对象删除时的操作,调用disconnect释放连接try:self.disconnect()except Exception:pass

核心的链接建立方法是通过socket模块实现:

    def _connect(self):err = Nonefor res in socket.getaddrinfo(self.host, self.port, 0,socket.SOCK_STREAM):family, socktype, proto, canonname, socket_address = ressock = Nonetry:sock = socket.socket(family, socktype, proto)# TCP_NODELAYsock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)# TCP_KEEPALIVEif self.socket_keepalive:   #构造函数中默认 socket_keepalive=False,因此这里默认为短连接sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)for k, v in iteritems(self.socket_keepalive_options):sock.setsockopt(socket.SOL_TCP, k, v)# set the socket_connect_timeout before we connectsock.settimeout(self.socket_connect_timeout)  #构造函数中默认socket_connect_timeout=None,即连接为blocking的模式# connectsock.connect(socket_address)# set the socket_timeout now that we're connectedsock.settimeout(self.socket_timeout)  #构造函数中默认socket_timeout=Nonereturn sockexcept socket.error as _:err = _if sock is not None:sock.close()
.....

关闭链接的方法:

    def disconnect(self):"Disconnects from the Redis server"self._parser.on_disconnect()if self._sock is None:returntry:self._sock.shutdown(socket.SHUT_RDWR)  #先shutdown再closeself._sock.close()except socket.error:passself._sock = None

可以小结如下
1)默认情况下每创建一个Redis实例都会构造出一个ConnectionPool实例,每一次访问redis都会从这个连接池得到一个连接,操作完成后会把该连接放回连接池(连接并没有释放),可以构造一个统一的ConnectionPool,在创建Redis实例时,可以将该ConnectionPool传入,那么后续的操作会从给定的ConnectionPool获得连接,不会再重复创建ConnectionPool。
2)默认情况下没有设置keepalive和timeout,建立的连接是blocking模式的短连接。
3)不考虑底层tcp的情况下,连接池中的连接会在ConnectionPool.disconnect中统一销毁。

转载于:https://blog.51cto.com/caiguangguang/1583541

python redis链接建立实现分析相关推荐

  1. python redis事务_python redis事务源码及应用分析

    在多个客户端同时处理相同的数据时,不谨慎的操作很容易导致数据出错.一般的关系型数据库中有事务保证了数据操作的原子性,同样Redis中也设置了事务,可以理解为"将多个命令打包,然后一次性.按顺 ...

  2. Python新冠疫情可视化分析系统 计算机专业毕业设计源码08504

    摘 要 文中首先对新冠疫情可视化分析的项目需求进行了背景分析,接着介绍了项目的总体设计思路,然后具体阐述了疫情数据库的设计.疫情数据的查询.疫情数据的展示,并分析了核心代码.文中利用MySQL数据库存 ...

  3. Python+审计实务与案例分析库 毕业设计-附源码211526

    Python审计实务与案例分析库 摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识 ...

  4. python代码弄成网站_原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想)...

    原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想) 总体思想: 希望让调用方通过 http调用传入一个需要生成图片的网页链接生成一个网页的图片并返回图片链接 最终调用 ...

  5. 原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想)...

    原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想) 总体思想:     希望让调用方通过 http调用传入一个需要生成图片的网页链接生成一个网页的图片并返回图片链接 ...

  6. 【翻译】Tricorder-谷歌如何建立程序分析的生态系统

    I. 介绍II. 背景A. 开发流程B. 谷歌的程序分析III. 谷歌程序分析理念A. 0误报率B. 授权用户做出贡献C. 改进数据驱动的可用性D. 工作流集成是关键E. 项目级别定制,而不是用户定制 ...

  7. 如何用 Python 和 API 收集与分析网络数据?

    摘自 https://www.jianshu.com/p/d52020f0c247 本文以一款阿里云市场历史天气查询产品为例,为你逐步介绍如何用 Python 调用 API 收集.分析与可视化数据.希 ...

  8. 基于Python的京东商品信息分析与实现

    随着信息技术和互联网技术的快速发展,利用数据采集技术实现用户感兴趣的数据收集分析成为很多互联网公司研究讨论的热门话题.通过对基于京东商品的数据采集进行商品价格动态变化的需求进行调查分析,发现作为研究商 ...

  9. python 源代码剖析mobi_预测分析:Python语言实现

    预测分析:Python语言实现 下载 mobi epub pdf ☆☆☆☆☆ [美] 约瑟夫·巴布科克 著,余水清 译 下载链接在页面底部 发表于2021-03-01 类似图书 点击查看全场最低价 图 ...

最新文章

  1. 「咖啡馆」里的任正非:开放的技术和商业,不会遵循「丛林法则」
  2. 1.7 元注解作用及使用
  3. idea中git提交代码更改作者名字(亲测)
  4. ISA Server服务器故障恢复一例系统盘符更换之后的应对方法
  5. opengl es java_java – 在Android OpenGL ES App中加载纹理
  6. hadoop java配置环境变量_hadoop2.7.2修改配置文件,配置linux java环境变量
  7. 计算机内存插在主板的哪个槽,四个内存插槽,这是正确的安装顺序
  8. 网易有数的“正确”使用方式——洞察数据中隐藏的故事
  9. 【Java从0到架构师】Zookeeper - 安装、核心工作机制、基本命令
  10. 爱上MVC系列~过滤器实现对响应流的处理
  11. 【C#】反射与面向接口的架构
  12. linux更新电池驱动下载,Linux 5.13电源管理与ACPI更新已提交
  13. C4droid导出程序
  14. 22nm 与 28nm 工艺的比较
  15. 基于RT-Thread的光照强度传感器BH1750FVI 软件包
  16. SAP 特别总账标识和备选统驭科目
  17. if test 用法
  18. 外贸企业电子邮箱哪个好?外贸邮箱怎么选择?
  19. raspberry pi_我如何从Mac Mini迁移到Raspberry Pi
  20. C语言与Java实现:数制转换

热门文章

  1. AI干货系列一:为什么AI预测更智能?
  2. SAP EWM - 物料主数据 - EWM系统存储视图属性
  3. 技术总监和CTO的区别 浅谈CTO的作用----软件公司如何开源节流(一)
  4. CTO集体怒吼:我到底要不要继续写代码(下篇)
  5. 【机器学习基本理论】详解最大后验概率估计(MAP)的理解
  6. 干货丨一份不可多得的深度学习技巧指南
  7. 细胞如何获得秩序?除了形成细胞器,还可以发生相分离
  8. 高文院士:中国在AI领域有哪些长板和短板
  9. 赛迪展望 | 一文了解“2021年中国先进计算产业发展趋势”
  10. Nature子刊超越诺贝尔经典理论:神经科学研究路漫漫...