我不清楚连接池是如何工作的,以及如何正确使用它们。我希望有人可以详细说明。我在下面勾画了我的用例:
settings.py:
import redis
def get_redis_connection():
return redis.StrictRedis(host='localhost', port=6379, db=0)
task1.py
import settings
connection = settings.get_redis_connection()
def do_something1():
return connection.hgetall(...)
task2.py
import settings
connection = settings.get_redis_connection()
def do_something1():
return connection.hgetall(...)
等
基本上我有一个返回redis连接的setting.py文件,以及几个获取redis连接的不同任务文件,然后运行操作。因此每个任务文件都有自己的redis实例(可能非常昂贵)。什么是优化此过程的最佳方式。是否可以在此示例中使用连接池?有没有更有效的方法来设置这种模式?
对于我们的系统,我们有相同模式的十几个任务文件,我注意到我们的请求变慢了。
由于
答案 0 :(得分:17)
Redis-py为您提供了一个连接池,您可以从中检索连接。连接池创建一组连接,您可以根据需要使用这些连接(完成后 - 将连接返回到连接池以供进一步重用)。尝试在不丢弃它们的情况下即时创建连接(即不使用池或不正确使用池)将使您与redis的连接过多(直到达到连接限制)。
您可以选择在init方法中设置连接池并使池全局化(如果全局不舒服,您可以查看其他选项)。
redis_pool = None
def init():
global redis_pool
print("PID %d: initializing redis pool..." % os.getpid())
redis_pool = redis.ConnectionPool(host='10.0.0.1', port=6379, db=0)
然后,您可以从池中检索连接:
redis_conn = redis.Redis(connection_pool=redis_pool)
另外,我假设您正在使用hiredis和redis-py,因为它应该在某些情况下提高性能。您是否还检查了使用现有设置打开redis服务器的连接数,因为它很可能非常高?您可以使用INFO命令获取该信息:
redis-cli info
检查客户端部分,您会在其中看到“ connected_clients ”字段,该字段将告诉您当时已向redis服务器开放的连接数。
答案 1 :(得分:8)
你应该使用基于redton-py的单例(borg模式)包装器,它将为你的所有文件提供一个公共连接池。 每当你使用这个包装类的对象时, 它将使用相同的连接池。
REDIS_SERVER_CONF = {
'servers' : {
'main_server': {
'HOST' : 'X.X.X.X',
'PORT' : 6379 ,
'DATABASE':0
}
}
}
import redis
class RedisWrapper(object):
shared_state = {}
def __init__(self):
self.__dict__ = self.shared_state
def redis_connect(self, server_key):
redis_server_conf = settings.REDIS_SERVER_CONF['servers'][server_key]
connection_pool = redis.ConnectionPool(host=redis_server_conf['HOST'], port=redis_server_conf['PORT'],
db=redis_server_conf['DATABASE'])
return redis.StrictRedis(connection_pool=connection_pool)
用法:
r_server = RedisWrapper().redis_connect(server_key='main_server')
r_server.ping()
<强>更新强>
如果您的文件作为不同的进程运行,您将必须使用redis代理,它将为您汇集连接,而不是直接连接到redis,您将不得不使用代理。 一个非常稳定的redis(和memcached)代理是由twitter创建的twemproxy,主要目的是减少开放连接。
答案 2 :(得分:5)
这是来自奶酪店page的引用。
在幕后,redis-py使用连接池来管理与Redis服务器的连接。 默认情况下,您创建的每个Redis实例将依次创建自己的连接池。您可以通过将已创建的连接池实例传递给Redis类的connection_pool参数来覆盖此行为并使用现有连接池。您可以选择执行此操作以实现客户端分片,或者对如何管理连接进行更精细的控制。
pool = redis.ConnectionPool(host='localhost', port=6379, db=0) r = redis.Redis(connection_pool=pool)
此外,实例are thread-safe:
可以在线程之间安全地共享Redis客户端实例。在内部,连接实例仅在命令执行期间从连接池中检索,并在之后直接返回到池。命令执行永远不会修改客户端实例上的状态。
你说:
因此每个任务文件都有自己的redis实例(可能非常昂贵)。 ...对于我们的系统,我们有相同模式的十几个任务文件,并且我注意到我们的请求变慢了。
几十个连接几乎不可能减慢Redis服务器的速度。但是因为你的代码在幕后使用了连接池,所以问题就在于连接本身。 Redis是内存存储,因此在大多数可以想象的情况下都非常快。所以我宁愿在任务中寻找问题。
来自@ user3813256的评论。是的,他在任务级别使用连接池。使用redis
包的内置连接池的常规方法是共享连接。最简单的方法是,settings.py
可能如下所示:
import redis
connection = None
def connect_to_redis():
global connection
connection = redis.StrictRedis(host='localhost', port=6379, db=0)
然后在你的应用程序调用{{1}}的引导中的某个地方。然后在任务模块中使用import connect_to_redis
。