【问题标题】:python Redis Connectionspython Redis 连接
【发布时间】:2012-11-06 01:50:03
【问题描述】:

我正在使用带有 python 的 Redis 服务器。

我的应用程序是多线程的(我每个进程使用 20 - 32 个线程)而且我也 我在不同的机器上运行应用程序。

我注意到有时 Redis cpu 使用率为 100%,而 Redis 服务器变得无响应/缓慢。

我想为每个应用程序使用 1 个总共 4 个连接的连接池。 因此,例如,如果我最多在 20 台机器上运行我的应用程序,那么应该有 20*4 = 80 个到 redis 服务器的连接。

POOL = redis.ConnectionPool(max_connections=4, host='192.168.1.1', db=1, port=6379)
R_SERVER = redis.Redis(connection_pool=POOL)

class Worker(Thread):

    def __init__(self):
        self.start()

    def run(self):
        while True:
            key = R_SERVER.randomkey()
            if not key: break
            value = R_SERVER.get(key)


    def _do_something(self, value):
        # do something with value
        pass

if __name__ = '__main__':
    num_threads = 20
    workers = [Worker() for _ in range(num_threads)]
    for w in workers:
       w.join()

当执行命令时,上面的代码应该运行从最大大小为 4 的连接池中获取连接的 20 个线程。

什么时候释放连接?

根据这段代码(https://github.com/andymccurdy/redis-py/blob/master/redis/client.py):

    #### 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:
        connection.disconnect()
        connection.send_command(*args)
        return self.parse_response(connection, command_name, **options)
    finally:
        pool.release(connection)

每条命令执行后,释放连接,回到池中

有人可以验证我是否正确理解了这个想法,并且上面的示例代码可以按描述工作吗?

因为当我看到redis连接时,总是有4个以上。

编辑:我刚刚在代码中注意到该函数在finally 之前有一个return 语句。那么finally的目的是什么?

【问题讨论】:

  • 无论是否异常,finally 块都会被执行。这是一个 DRY 用例。
  • 您提到 Redis 服务器有时会变得无响应。你在使用 Windows 吗?如果是这样,Windows 版本确实会将数据库异步保存到磁盘,这将导致 Redis 挂起,直到完成。
  • 即使在 unix 环境中,保存也可能代价高昂。如果您使用的是 RDB 转储序列化策略,Redis 会分叉内存 DB 的副本以写出。如果您的数据库大小 > 1/2 可用内存,那么当它尝试这样做时会发生不好的事情。如果这是问题所在,请尝试使用 AOF 策略,或关闭序列化。
  • 您应检测不响应的原因。较大的连接池不太可能解决您的问题,因为 Redis 在设计上总是在一个进程中运行,其他进程必须等待。

标签: python redis


【解决方案1】:

正如 Matthew Scragg 提到的,finally 子句在测试结束时执行。在这种特殊情况下,它用于在完成连接后将连接释放回池,而不是让它保持打开状态。

至于无响应,请查看您的服务器在做什么。您的 Redis 实例的内存限制是多少?您多久保存一次磁盘?您是否在基于 Xen 的 VM(例如 AWS 实例)上运行?您是否正在运行复制,如果有,有多少从属服务器,它们是否处于良好状态,或者它们是否经常要求完全重新同步数据?您的任何命令是否“保存”?

您可以使用命令行界面回答其中一些问题。例如 redis-cli info persistence 会告诉您有关保存到磁盘的过程的信息,redis-cli info memory 会告诉您有关您的内存消耗的信息。

获取持久化信息的时候要专门看rdb_last_bgsave_statusrdb_last_bgsave_time_sec。这些将告诉您上次保存是否成功以及花费了多长时间。花费的时间越长,您遇到资源问题的可能性就越大,您遇到可能表现为无响应的减速的可能性就越大。

【讨论】:

    【解决方案2】:

    尽管前面有一个 return 语句,但最终块将始终运行。你可以看看 redis-py/connection.py , pool.release(connection) 只把连接放到可用连接池中,所以连接仍然存在。 关于 redis 服务器 cpu 的使用,您的应用程序将始终发送请求并且没有中断或睡眠,所以它只是使用越来越多的 cpu,而不是内存。而cpu使用率与打开文件数无关。

    【讨论】:

      猜你喜欢
      • 2018-07-16
      • 2012-10-09
      • 2021-03-13
      • 2022-11-07
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      • 2018-04-02
      • 2019-09-12
      相关资源
      最近更新 更多