最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python與Redis的連接教程

 更新時(shí)間:2015年04月22日 16:13:41   投稿:goldensun  
這篇文章主要介紹了Python與Redis的連接教程,Redis是一個(gè)高性能的基于內(nèi)存的數(shù)據(jù)庫,需要的朋友可以參考下

今天在寫zabbix storm job監(jiān)控腳本的時(shí)候用到了python的redis模塊,之前也有用過,但是沒有過多的了解,今天看了下相關(guān)的api和源碼,看到有ConnectionPool的實(shí)現(xiàn),這里簡單說下。
在ConnectionPool之前,如果需要連接redis,我都是用StrictRedis這個(gè)類,在源碼中可以看到這個(gè)類的具體解釋:
 
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這個(gè)類之后,可以使用如下方法
 

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

這里Redis是StrictRedis的子類
簡單分析如下:
在StrictRedis類的__init__方法中,可以初始化connection_pool這個(gè)參數(shù),其對應(yīng)的是一個(gè)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的實(shí)例執(zhí)行具體的命令時(shí)會調(diào)用execute_command方法,這里可以看到具體實(shí)現(xiàn)是從連接池中獲取一個(gè)具體的連接,然后執(zhí)行命令,完成后釋放連接:

 

  # COMMAND EXECUTION AND PROTOCOL PARSING
  def execute_command(self, *args, **options):
    "Execute a command and return a parsed response"
    pool = self.connection_pool
    command_name = args[0]
    connection = pool.get_connection(command_name, **options) #調(diào)用ConnectionPool.get_connection方法獲取一個(gè)連接
    try:
      connection.send_command(*args) #命令執(zhí)行,這里為Connection.send_command
      return self.parse_response(connection, command_name, **options)
    except (ConnectionError, TimeoutError) as e:
      connection.disconnect()
      if not connection.retry_on_timeout and isinstance(e, TimeoutError):
        raise
      connection.send_command(*args) 
      return self.parse_response(connection, command_name, **options)
    finally:
      pool.release(connection) #調(diào)用ConnectionPool.release釋放連接

在來看看ConnectionPool類:

class ConnectionPool(object): 
    ...........
  def __init__(self, connection_class=Connection, max_connections=None,
         **connection_kwargs):  #類初始化時(shí)調(diào)用構(gòu)造函數(shù)
    max_connections = max_connections or 2 ** 31
    if 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 #設(shè)置對應(yīng)的參數(shù)
    self.connection_kwargs = connection_kwargs
    self.max_connections = max_connections
    self.reset() #初始化ConnectionPool 時(shí)的reset操作
  def reset(self):
    self.pid = os.getpid()
    self._created_connections = 0 #已經(jīng)創(chuàng)建的連接的計(jì)數(shù)器
    self._available_connections = []  #聲明一個(gè)空的數(shù)組,用來存放可用的連接
    self._in_use_connections = set() #聲明一個(gè)空的集合,用來存放已經(jīng)在用的連接
    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時(shí),因?yàn)開available_connections是一個(gè)空的數(shù)組,
      會直接調(diào)用make_connection方法
    except IndexError:
      connection = self.make_connection()
    self._in_use_connections.add(connection)  #向代表正在使用的連接的集合中添加元素
    return connection  
  def make_connection(self): #在_available_connections數(shù)組為空時(shí)獲取連接調(diào)用的方法
    "Create a new connection"
    if self._created_connections >= self.max_connections:  #判斷創(chuàng)建的連接是否已經(jīng)達(dá)到最大限制,max_connections可以通過參數(shù)初始化
      raise ConnectionError("Too many connections")
    self._created_connections += 1  #把代表已經(jīng)創(chuàng)建的連接的數(shù)值+1
    return self.connection_class(**self.connection_kwargs)   #返回有效的連接,默認(rèn)為Connection(**self.connection_kwargs)
  def release(self, connection): #釋放連接,鏈接并沒有斷開,只是存在鏈接池中
    "Releases the connection back to the pool"
    self._checkpid()
    if connection.pid != self.pid:
      return
    self._in_use_connections.remove(connection)  #從集合中刪除元素
    self._available_connections.append(connection) #并添加到_available_connections 的數(shù)組中
  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最終調(diào)用的是Connection.send_command方法,關(guān)閉鏈接為 Connection.disconnect方法,而Connection類的實(shí)現(xiàn):
 

class Connection(object):
  "Manages TCP communication to and from a Redis server"
  def __del__(self):  #對象刪除時(shí)的操作,調(diào)用disconnect釋放連接
    try:
      self.disconnect()
    except Exception:
      pass

核心的鏈接建立方法是通過socket模塊實(shí)現(xiàn):

 
   

 def _connect(self):
    err = None
    for res in socket.getaddrinfo(self.host, self.port, 0,
                   socket.SOCK_STREAM):
      family, socktype, proto, canonname, socket_address = res
      sock = None
      try:
        sock = socket.socket(family, socktype, proto)
        # TCP_NODELAY
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        # TCP_KEEPALIVE
        if self.socket_keepalive:  #構(gòu)造函數(shù)中默認(rèn) socket_keepalive=False,因此這里默認(rèn)為短連接
          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 connect
        sock.settimeout(self.socket_connect_timeout) #構(gòu)造函數(shù)中默認(rèn)socket_connect_timeout=None,即連接為blocking的模式
        # connect
        sock.connect(socket_address)
        # set the socket_timeout now that we're connected
        sock.settimeout(self.socket_timeout) #構(gòu)造函數(shù)中默認(rèn)socket_timeout=None
        return sock
      except socket.error as _:
        err = _
        if sock is not None:
          sock.close()
.....

關(guān)閉鏈接的方法:
 

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

       
可以小結(jié)如下
1)默認(rèn)情況下每創(chuàng)建一個(gè)Redis實(shí)例都會構(gòu)造出一個(gè)ConnectionPool實(shí)例,每一次訪問redis都會從這個(gè)連接池得到一個(gè)連接,操作完成后會把該連接放回連接池(連接并沒有釋放),可以構(gòu)造一個(gè)統(tǒng)一的ConnectionPool,在創(chuàng)建Redis實(shí)例時(shí),可以將該ConnectionPool傳入,那么后續(xù)的操作會從給定的ConnectionPool獲得連接,不會再重復(fù)創(chuàng)建ConnectionPool。
2)默認(rèn)情況下沒有設(shè)置keepalive和timeout,建立的連接是blocking模式的短連接。
3)不考慮底層tcp的情況下,連接池中的連接會在ConnectionPool.disconnect中統(tǒng)一銷毀。

相關(guān)文章

  • Python中弱引用的神奇用法與原理詳解

    Python中弱引用的神奇用法與原理詳解

    弱引用在很多語言中都存在,最常用來解決循環(huán)引用問題,下面這篇文章主要給大家介紹了關(guān)于Python中弱引用的神奇用法與原理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • 一文淺析Python中常用的魔法函數(shù)使用指南

    一文淺析Python中常用的魔法函數(shù)使用指南

    Python中的魔法函數(shù)(Magic Methods),也稱為雙下劃線方法(dunder methods),是Python面向?qū)ο缶幊痰暮诵臋C(jī)制之一,本文將全面介紹這些魔法函數(shù),助你寫出更Pythonic的代碼
    2025-12-12
  • 詳解python中的index函數(shù)用法

    詳解python中的index函數(shù)用法

    這篇文章主要介紹了詳解python中的index函數(shù)用法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-08-08
  • 基于PyQt5制作一個(gè)PDF文件合并器

    基于PyQt5制作一個(gè)PDF文件合并器

    PDF文件合并工具是非常好用可以把多個(gè)pdf文件合并成一個(gè),本文將利用Python中的PyQT5模塊,制作一個(gè)簡易的PDF文件合并器,感興趣的可以了解一下
    2022-03-03
  • Flask??response?對象詳情

    Flask??response?對象詳情

    在?Flask?中,響應(yīng)使用?Response?對象表示,響應(yīng)報(bào)文中的大部分內(nèi)容由服務(wù)器處理,一般情況下,我們只負(fù)責(zé)返回主體內(nèi)容即可。在之前的文章中,我們了解到?Flask?會先匹配請求?url?的路由,調(diào)用對應(yīng)的視圖函數(shù),視圖函數(shù)的返回值構(gòu)成了響應(yīng)報(bào)文的主體內(nèi)容。
    2021-11-11
  • Python算法思想集結(jié)深入理解動態(tài)規(guī)劃

    Python算法思想集結(jié)深入理解動態(tài)規(guī)劃

    這篇文章主要為大家介紹了Python算法思想集結(jié)深入理解動態(tài)規(guī)劃詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Python中join()方法完全使用指南(參數(shù)要求與常見用法)

    Python中join()方法完全使用指南(參數(shù)要求與常見用法)

    join()是Python中字符串操作的核心方法之一,但許多開發(fā)者在使用時(shí)經(jīng)常遇到TypeError或意外結(jié)果,本文將全面解析' '.join()的參數(shù)要求,通過實(shí)際示例展示正確用法,并總結(jié)常見問題的解決方案,需要的朋友可以參考下
    2025-06-06
  • 一文帶你玩轉(zhuǎn)Python必備的幾種數(shù)據(jù)格式

    一文帶你玩轉(zhuǎn)Python必備的幾種數(shù)據(jù)格式

    在Python開發(fā)中,數(shù)據(jù)格式的選擇直接影響著程序的性能和可維護(hù)性,本文將詳細(xì)介紹Python開發(fā)中最常用的幾種數(shù)據(jù)格式,希望可以幫助大家選擇最合適的數(shù)據(jù)表示方式
    2025-06-06
  • Python import用法以及與from...import的區(qū)別

    Python import用法以及與from...import的區(qū)別

    這篇文章主要介紹了Python import用法以及與from...import的區(qū)別,本文簡潔明了,很容易看懂,需要的朋友可以參考下
    2015-05-05
  • Python中subprocess.run()執(zhí)行命令、檢查狀態(tài)與結(jié)果處理深入理解

    Python中subprocess.run()執(zhí)行命令、檢查狀態(tài)與結(jié)果處理深入理解

    這篇文章主要介紹了Python中subprocess.run()執(zhí)行命令、檢查狀態(tài)與結(jié)果處理的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2025-04-04

最新評論

达尔| 波密县| 阳谷县| 新蔡县| 兴城市| 将乐县| 岚皋县| 读书| 县级市| 逊克县| 孝感市| 乐平市| 南澳县| 遂平县| 包头市| 伊宁市| 神农架林区| 渝中区| 临泉县| 三河市| 广灵县| 儋州市| 舒城县| 彰化市| 区。| 福海县| 汶上县| 博客| 罗山县| 哈密市| 土默特左旗| 临湘市| 斗六市| 沁水县| 烟台市| 新源县| 涞源县| 卢湾区| 静海县| 务川| 正镶白旗|