【发布时间】: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 在设计上总是在一个进程中运行,其他进程必须等待。