redis-py连接池的实现

说起连接池,可能很多人直接望而却步,觉得好复杂,还是直接调用别人现成的好了,其实都是连接池也是扮猪吃老虎。

但是之前看redis-py连接池的实现,觉得好简单,但是却又很巧妙,正好最近又在研究redis-py的连接池,将连接池相关的实现抽象出来,接单说明一下。

class Connection:
    def __init(self, **db_info):
        """初始化需要一些redis服务器的连接信息,此处以db_info代替"""
        self._sock = None
        pass
        
        
    def connect(self):
        """供上层调用"""
        if not self._sock:
            self._connect()
            
        pass
        
    def _connect(self):
        """同redis服务器建立socket"""
        self._sock = socket(**db_info)
    
    def disconnect(self):
        """关闭socket连接,此处很巧妙"""
        """连接对象不会销毁,内部的socket会被销毁"""
        self.socket = None
        
    def send_command(self, **args):
        if not self._socket:
            self.connect()
        self._sock.sendall(**args)
        
    def read_response(self):
        return self._sock.readall()
    
    
class ConnectionPool:
    def __init__(self, **pool_config, **db_info):
        """实例化需要连接池配置(如连接池大小),数据库连接信息"""
        self.reset()
        
    def reset(self):
        """初始化内部维护的连接"""
        self._available_connections = []
        self._in_use_connections = set()
    
    def make_connection(self):
        """创建新的连接对象"""
        conn = Connection(**db_info)
        
    def get_connection(self):
        """获取一条连接,供上层调用"""
        if self._available_connections:
            conn = self._available_connections
        else:
            conn = self.make_connection()
        
        self._in_use_connections.add(conn)
        return conn
        
    def release(self, connection):
        """释放单个连接对象到连接池"""
        self._in_use_connections.remove(connection)
        self._available_connections.append(connection)
    
    def disconnect(self):
        """将关闭所有在用的,可用的连接对象"""
        all_conns = chain(self._available_connections,
                          self._in_use_connections)
        for connection in all_conns:
            connection.disconnect()
        
class Redis:
    """redis对象,实例化之后内部同时实例化一个连接池对象"""
    def __init__(self, **pool_config, **db_info):
        self.pool = ConnectionPool(**pool_config, **db_info)
        
    def execute_command(data):
        """从连接池取出一条连接,发送信息,释放给连接池"""
        connection = self.pool.get_connection()
        try:
            connection.send_command(data)
        except:
            connection.disconnect()
        pool.release(connection)
        

当然关于上面的代码遗漏了很多的防御代码 ,比如检测父子进程是否共用一个相同的描述符等,但是我觉的把redis-py连接池的关键表达出来了。

连接池内部维护两个集合,一个可用的连接集合,一个在用的连接集合,当上层获取连接的时候,从可用集合拿出一个返回,同时加到在用集合。

还有一个很巧妙的细节,就是连接在传递数据出错的时候,不是销毁连接对象,而是销毁连接对象内部的socket。因为连接对象一旦实例化就没有足够的理由去销毁它,即使出错也是socket连接出错,销毁socket就好了,避免了连接对象的频繁生成、销毁。

最后推荐一下老钱的《Redis 深度历险:核心原理与应用实践

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值