亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

python redis之連接池的原理

系統(tǒng) 1805 0

python redis之連接池的原理

?

轉(zhuǎn)載地址

什么是連接池

通常情況下, 當(dāng)我們需要做redis操作時(shí), 會(huì)創(chuàng)建一個(gè)連接, 并基于這個(gè)連接進(jìn)行redis操作, 操作完成后, 釋放連接,

一般情況下, 這是沒(méi)問(wèn)題的, 但當(dāng)并發(fā)量比較高的時(shí)候, 頻繁的連接創(chuàng)建和釋放對(duì)性能會(huì)有較高的影響

于是, 連接池就發(fā)揮作用了

連接池的原理是, 通過(guò)預(yù)先創(chuàng)建多個(gè)連接, 當(dāng)進(jìn)行redis操作時(shí), 直接獲取已經(jīng)創(chuàng)建的連接進(jìn)行操作, 而且操作完成后, 不會(huì)釋放, 用于后續(xù)的其他redis操作

這樣就達(dá)到了避免頻繁的redis連接創(chuàng)建和釋放的目的, 從而提高性能了

?

原理

那么, 在redis-py中, 他是怎么進(jìn)行連接池管理的呢

連接池使用

首先看下如何進(jìn)行連接池操作的

              rdp = redis.ConnectionPool(host=
              
                '
              
              
                127.0.0.1
              
              
                '
              
              , port=6379, password=
              
                '
              
              
                xxxxx
              
              
                '
              
              
                )
rdc 
              
              = redis.StrictRedis(connection_pool=
              
                rdp)
rdc.set(
              
              
                '
              
              
                name
              
              
                '
              
              , 
              
                '
              
              
                Yi_Zhi_Yu
              
              
                '
              
              
                )
rdc.get(
              
              
                '
              
              
                name
              
              
                '
              
              )
            

原理解析

當(dāng)redis.ConnectionPool 實(shí)例化的時(shí)候, 做了什么

              
                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:
            
              
              
                raise
              
               ValueError(
              
                '
              
              
                "max_connections" must be a positive integer
              
              
                '
              
              
                )

        self.connection_class 
              
              =
              
                 connection_class
        self.connection_kwargs 
              
              =
              
                 connection_kwargs
        self.max_connections 
              
              = max_connections
            

這個(gè)連接池的實(shí)例化其實(shí)未做任何真實(shí)的redis連接, 僅僅是設(shè)置最大連接數(shù), 連接參數(shù)和連接類

StrictRedis 實(shí)例化的時(shí)候, 又做了什么

              
                def
              
              
                __init__
              
              (self, ...connection_pool=
              
                None...):
        
              
              
                if
              
              
                not
              
              
                 connection_pool:
            ...
            connection_pool 
              
              = ConnectionPool(**
              
                kwargs)
        self.connection_pool 
              
              = connection_pool
            

以上僅保留了關(guān)鍵部分代碼

可以看出, 使用StrictRedis 即使不創(chuàng)建連接池, 他也會(huì)自己創(chuàng)建

到這里, 我們還沒(méi)有看到什么redis連接真實(shí)發(fā)生

繼續(xù)

下一步就是 set ?操作了, 很明顯, 這個(gè)時(shí)候一定會(huì)發(fā)生redis連接(要不然怎么set)

              
                def
              
               set(self, name, value, ex=None, px=None, nx=False, xx=
              
                False):
    ...
    
              
              
                return
              
               self.execute_command(
              
                '
              
              
                SET
              
              
                '
              
              , *pieces)
            

我們繼續(xù)看看 execute_command

              
                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)
        
              
              
                try
              
              
                :
            connection.send_command(
              
              *
              
                args)
            
              
              
                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)
              
            

終于, 在這我們看到到了連接創(chuàng)建

              connection = pool.get_connection(command_name, **options)
            

這里調(diào)用的是 ConnectionPool 的get_connection

              
                def
              
               get_connection(self, command_name, *keys, **
              
                options):
        
              
              
                "
              
              
                Get a connection from the pool
              
              
                "
              
              
                
        self._checkpid()
        
              
              
                try
              
              
                :
            connection 
              
              =
              
                 self._available_connections.pop()
        
              
              
                except
              
              
                 IndexError:
            connection 
              
              =
              
                 self.make_connection()
        self._in_use_connections.add(connection)
        
              
              
                return
              
               connection
            

如果有可用的連接, 獲取可用的鏈接, 如果沒(méi)有, 創(chuàng)建一個(gè)

              
                def
              
              
                 make_connection(self):
        
              
              
                "
              
              
                Create a new connection
              
              
                "
              
              
                if
              
               self._created_connections >=
              
                 self.max_connections:
            
              
              
                raise
              
               ConnectionError(
              
                "
              
              
                Too many connections
              
              
                "
              
              
                )
        self._created_connections 
              
              += 1
        
              
                return
              
               self.connection_class(**self.connection_kwargs)
            

終于, 我們看到了, 在這里創(chuàng)建了連接

在ConnectionPool的實(shí)例中, 有兩個(gè)list, 依次是 _available_connections ,? _in_use_connections ,

分別表示 可用的連接集合 正在使用的連接集合 , 在上面的 get_connection 中, 我們可以看到獲取連接的過(guò)程是

  1. 從可用連接集合嘗試獲取連接,
  2. 如果獲取不到, 重新創(chuàng)建連接
  3. 將獲取到的連接添加到正在使用的連接集合

上面是往 _in_use_connections 里添加連接的, 這種連接表示正在使用中, 那是什么時(shí)候?qū)⒄谑褂玫倪B接放回到可用連接列表中的呢

這個(gè)還是在 execute_command 里, 我們可以看到在執(zhí)行redis操作時(shí), 在 finally 部分, 會(huì)執(zhí)行一下

              pool.release(connection)
            

連接池對(duì)象調(diào)用 release 方法, 將連接從 _in_use_connections ?放回? _available_connections , 這樣后續(xù)的連接獲取就能再次使用這個(gè)連接了

release ?方法如下

              
                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)
              
            

總結(jié)

至此, 我們把連接池的管理流程走了一遍, ConnectionPool通過(guò)管理 可用連接列表 ( _available_connections ) 和? 正在使用的連接列表 從而實(shí)現(xiàn)連接池管理

?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 热久久在线观看 | h片免费看 | 伦理一区二区 | 尻逼影院 | h网站国产| 欧美精品国产 | 国产你懂得| 色婷婷精品大视频在线蜜桃视频 | 国产一区二区播放 | 久久久噜久噜久久综合 | 色吧久久| 欧美美女被爆操 | 精品色 | 奇米影视在线视频8888 | 久久久久无码国产精品一区 | 欧美大屁股精品毛片视频 | 国产精品一区二区免费 | 日本久久精品视频 | 老子影院午夜伦手机不卡6080 | 久久99国产精一区二区三区 | 有码在线| 久久精品国产亚洲精品 | 中文字幕日韩专区 | 久久免费视频7 | 亚洲国产成人久久精品动漫 | 男人天堂日韩 | 四虎影视永久免费观看地址 | 欧美一级高清片在线 | 特级一级黄色片 | 日本深夜影院 | 日欧毛片| 成年女人在线观看 | 天天草天天| 国产精品v免费视频 | 精品一区二区日本高清 | 亚洲精品国产一区二区在线 | 一区二区手机视频 | 热99热| 91成人爽a毛片一区二区 | 4hu影院在线观看 | 韩日性视频 |