代码之家  ›  专栏  ›  技术社区  ›  Muthu

Redis Python客户端打开了许多连接

  •  2
  • Muthu  · 技术社区  · 7 年前

    我正在使用以下代码连接Redis服务器。 我看到大量连接处于TIME\u WAIT状态。可能有什么问题?

    root@ubuntu:~$ netstat | grep :6479 | grep TIME_WAIT |wc -l
    9061
    root@ubuntu:~$ netstat | grep :6479 | grep ESTABLISHED |wc -l
    7
    

    我曾想过使用以下代码在Redis server上完成操作后关闭连接。但我发现了这个错误。

    @staticmethod
    def disconnectRedisConnection(r_server):
        if r_server is not None and r_server:
            r_server.connection.disconnect()
    

    r_server.connection.disconnect()
    AttributeError: 'Redis' object has no attribute 'connection'
    

    对于使用Redis完成操作后等待连接/关闭连接的巨大时间有何想法?

    import threading
    from time import sleep
    import time, datetime
    import traceback
    import CACHE_CONST
    import json
    import os
    
    import MySQLdb
    import redis
    
    # Static methods to interact with the Redis cache server
    class CacheUtil(object):
    
        # Log Errors
        @staticmethod
        def log_message(msg):
            log_file = None
            log_file = open (os.path.abspath(CACHE_CONST.REDIS_LOG_FILE), "a")
            print(msg)
            if (log_file):
                message = time.strftime("%d-%m-%Y %H:%M:%S")    
                message += " :: " + str(msg)
                log_file.write(message + "\n")
    
        @staticmethod
        def saveToCache(hashName, hashValue):
            r_server = CacheUtil.getRedisConnection()
            r_server.hmset(hashName, hashValue)
            CacheUtil.disconnectRedisConnection(r_server)
    
        @staticmethod
        def getTrackerDetailsByID(trackerId):
            trackerDetail = None
            r_server = None
            hashName = "tDetails:" + str(trackerId)
            try:
                if trackerId is not None:
                    print("getTrackerDetailsByID ")
                    r_server = CacheUtil.getRedisConnection()
                    trackerDetail = r_server.hgetall(hashName)
                else:
                    CacheUtil.log_message("getDetailsByID failed with empty trackerId ")
            except:
                CacheUtil.log_message("getDetailsByID failed, ll fetch from DB " + str(traceback.format_exc()))
            finally:
                CacheUtil.disconnectRedisConnection(r_server)
            return trackerDetail
    
        @staticmethod
        def getRedisConnection():
            print("Get Redis Connection on Util ")
            r_server = redis.Redis(host=CACHE_CONST.REDIS_SERVER_URL, port=CACHE_CONST.REDIS_SERVER_PORT, db=0, password=CACHE_CONST.REDIS_PASS_PHRASE, socket_connect_timeout=2, socket_timeout=2)
            return r_server;
    
        @staticmethod
        def disconnectRedisConnection(r_server):
            if r_server is not None and r_server:
                r_server.connection.disconnect()
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   GuangshengZuo    7 年前

    实际上,当你打电话给 redis.Redis()

    每次发送redis之类的命令时。set()或其他,它将从其连接池中检索连接,并使用此连接发送此命令并等待回复。当请求完成后,它将连接放回连接池以供重用。因此,您不需要自己管理连接。看看这个 https://github.com/andymccurdy/redis-py 了解更多信息。

    import threading
    from time import sleep
    import time, datetime
    import traceback
    import CACHE_CONST
    import json
    import os
    
    import MySQLdb
    import redis
    r_server = redis.Redis(host=CACHE_CONST.REDIS_SERVER_URL, port=CACHE_CONST.REDIS_SERVER_PORT, db=0, password=CACHE_CONST.REDIS_PASS_PHRASE, socket_connect_timeout=2, socket_timeout=2)
    
    # Static methods to interact with the Redis cache server
    class CacheUtil(object):
    
        # Log Errors
        @staticmethod
        def log_message(msg):
            log_file = None
            log_file = open (os.path.abspath(CACHE_CONST.REDIS_LOG_FILE), "a")
            print(msg)
            if (log_file):
                message = time.strftime("%d-%m-%Y %H:%M:%S")    
                message += " :: " + str(msg)
                log_file.write(message + "\n")
    
        @staticmethod
        def saveToCache(hashName, hashValue):
            r_server.hmset(hashName, hashValue)
    
        @staticmethod
        def getTrackerDetailsByID(trackerId):
            hashName = "tDetails:" + str(trackerId)
            try:
                if trackerId is not None:
                    print("getTrackerDetailsByID ")
                    trackerDetail = r_server.hgetall(hashName)
                else:
                    CacheUtil.log_message("getDetailsByID failed with empty trackerId ")
            except:
                CacheUtil.log_message("getDetailsByID failed, ll fetch from DB " + str(traceback.format_exc()))
            return trackerDetail
    

    更新

        # 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)
        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)
    

    对于使用Redis完成操作后等待连接/关闭连接的时间过长有何想法

    enter image description here

    这是关于TCP连接终止过程的图像。当客户端(启动器)为服务器(接收器)FIN发送ACK时,它进入Time\u WAIT状态。

    最后一次确认时,该连接必须在TIME_WAIT状态下保持MSL的两倍。这让TCP (它们不使用序列号,也不由TCP重新传输),但因为另一方 将重新传输其FIN(它确实消耗序列号)。实际上,TCP总是会重新传输 直到收到最终确认。

    还有一篇关于 the purpose about TIME_WAIT