<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        Python與Redis的連接教程

        來源:懂視網 責編:小采 時間:2020-11-27 14:32:55
        文檔

        Python與Redis的連接教程

        Python與Redis的連接教程:今天在寫zabbix storm job監控腳本的時候用到了python的redis模塊,之前也有用過,但是沒有過多的了解,今天看了下相關的api和源碼,看到有ConnectionPool的實現,這里簡單說下。 在ConnectionPool之前,如果需要連接redis,我都是用StrictRed
        推薦度:
        導讀Python與Redis的連接教程:今天在寫zabbix storm job監控腳本的時候用到了python的redis模塊,之前也有用過,但是沒有過多的了解,今天看了下相關的api和源碼,看到有ConnectionPool的實現,這里簡單說下。 在ConnectionPool之前,如果需要連接redis,我都是用StrictRed

        今天在寫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 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) #調用ConnectionPool.get_connection方法獲取一個連接
         try:
         connection.send_command(*args) #命令執行,這里為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) #調用ConnectionPool.release釋放連接
        

        在來看看ConnectionPool類:

        class ConnectionPool(object): 
         ...........
         def __init__(self, connection_class=Connection, max_connections=None,
         **connection_kwargs): #類初始化時調用構造函數
         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 #設置對應的參數
         self.connection_kwargs = connection_kwargs
         self.max_connections = max_connections
         self.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 #把代表已經創建的連接的數值+1
         return 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:
         return
         self._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 = 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: #構造函數中默認 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 connect
         sock.settimeout(self.socket_connect_timeout) #構造函數中默認socket_connect_timeout=None,即連接為blocking的模式
         # connect
         sock.connect(socket_address)
         # set the socket_timeout now that we're connected
         sock.settimeout(self.socket_timeout) #構造函數中默認socket_timeout=None
         return sock
         except 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:
         return
         try:
         self._sock.shutdown(socket.SHUT_RDWR) #先shutdown再close
         self._sock.close()
         except socket.error:
         pass
         self._sock = None
        


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

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Python與Redis的連接教程

        Python與Redis的連接教程:今天在寫zabbix storm job監控腳本的時候用到了python的redis模塊,之前也有用過,但是沒有過多的了解,今天看了下相關的api和源碼,看到有ConnectionPool的實現,這里簡單說下。 在ConnectionPool之前,如果需要連接redis,我都是用StrictRed
        推薦度:
        標簽: 連接 步驟 方法
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲电影在线播放| 亚洲色欲久久久综合网| 亚洲另类视频在线观看| 日韩插啊免费视频在线观看| 亚洲AV无码精品色午夜在线观看| a毛片全部免费播放| 亚洲AV中文无码字幕色三| 久久精品私人影院免费看| 亚洲人成电影在在线观看网色| 永久在线观看免费视频| 亚洲成在人天堂一区二区| 8x8×在线永久免费视频| 亚洲欧洲国产视频| 成年美女黄网站18禁免费| 亚洲爆乳无码精品AAA片蜜桃| 国产在线播放免费| fc2免费人成在线| 亚洲精品天天影视综合网| 波多野结衣免费在线| 爱爱帝国亚洲一区二区三区| 中文字幕亚洲日本岛国片| 中文字幕无码免费久久| 亚洲中字慕日产2021| 日本a级片免费看| a级成人免费毛片完整版| 亚洲免费福利视频| 国产成人aaa在线视频免费观看 | 亚洲一卡一卡二新区无人区| 国产精品久免费的黄网站| 五月天婷婷免费视频| 亚洲专区在线视频| 在线日韩av永久免费观看| 黄床大片免费30分钟国产精品| 亚洲色图国产精品| 少妇亚洲免费精品| 无码精品一区二区三区免费视频| 亚洲国产精品网站在线播放 | 亚洲大尺码专区影院| 国产自产拍精品视频免费看| 中国极品美軳免费观看| 午夜在线a亚洲v天堂网2019|