首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何正确使用redis中的连接池?

如何正确使用redis中的连接池?
EN

Stack Overflow用户
提问于 2015-07-28 05:04:38
回答 3查看 53.4K关注 0票数 42

我不清楚连接池是如何工作的,以及如何正确使用它们。我希望有人能详细解释一下。我已经勾勒出我的用例如下:

settings.py:

代码语言:javascript
复制
import redis

def get_redis_connection():
    return redis.StrictRedis(host='localhost', port=6379, db=0)

task1.py

代码语言:javascript
复制
import settings

connection = settings.get_redis_connection()

def do_something1():
    return connection.hgetall(...)

task2.py

代码语言:javascript
复制
import settings

connection = settings.get_redis_connection()

def do_something1():
    return connection.hgetall(...)

等。

基本上,我有一个返回redis连接的setting.py文件,以及几个不同的任务文件,它们获取redis连接,然后运行操作。因此,每个任务文件都有自己的redis实例(这可能非常昂贵)。优化这个过程的最好方法是什么?在这个例子中可以使用连接池吗?有没有更有效的方法来设置这种模式?

对于我们的系统,我们有超过12个任务文件遵循相同的模式,我注意到我们的请求变慢了。

谢谢

EN

回答 3

Stack Overflow用户

发布于 2015-07-31 04:49:02

Redis-py为您提供了一个连接池,您可以从中检索连接。连接池创建一组连接,您可以根据需要使用这些连接(完成后,连接将返回到连接池以供进一步重用)。尝试在不丢弃连接的情况下动态创建连接(例如,不使用池或不正确使用池)会给redis留下太多的连接(直到您达到连接限制)。

您可以选择在init方法中设置连接池,并将连接池设置为全局连接池(如果对全局连接池感到不舒服,可以考虑其他选项)。

代码语言:javascript
复制
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)

然后,可以从池中检索连接,如下所示:

代码语言:javascript
复制
redis_conn = redis.Redis(connection_pool=redis_pool)

另外,我假设您使用hiredis和redis-py,因为在某些情况下它可以提高性能。你有没有检查过在你现有的设置下打开到redis服务器的连接数,因为它很可能是相当高的?您可以使用INFO命令来获取该信息:

代码语言:javascript
复制
redis-cli info

检查redis Clients部分,您将在其中看到"connected_clients“字段,该字段将告诉您在该时刻打开了多少个到服务器的连接。

票数 31
EN

Stack Overflow用户

发布于 2015-08-04 18:58:00

您应该使用一个基于单例( borg模式)的包装器来覆盖redis-py,它将为您的所有文件提供一个公共连接池。无论何时使用此包装器类的对象,它都将使用相同的连接池。

代码语言:javascript
复制
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)

用法:

代码语言:javascript
复制
r_server = RedisWrapper().redis_connect(server_key='main_server')
r_server.ping()

更新

如果您的文件作为不同的进程运行,您将不得不使用redis代理,它将为您汇集连接,而不是直接连接到redis,您将必须使用代理。一个非常稳定的redis (和memcached )代理是twitter创建的twemproxy,主要目的是减少开放连接。

票数 12
EN

Stack Overflow用户

发布于 2015-07-31 15:50:04

下面是芝士店page的一句话。

在幕后,redis-py使用连接池来管理到Redis服务器的连接。默认情况下,您创建的每个Redis实例都会创建自己的连接池。您可以通过将已经创建的连接池实例传递给Redis类的connection_pool参数来覆盖此行为并使用现有的连接池。您可以选择这样做,以便实现客户端分片,或者对如何管理连接进行更细粒度的控制。

池= redis.ConnectionPool(host='localhost',port=6379,db=0) r= redis.Redis(connection_pool=pool)

此外,实例are thread-safe

Redis客户端实例可以安全地在线程之间共享。在内部,连接实例仅在命令执行期间从连接池中检索,并在命令执行后直接返回到池中。命令执行永远不会修改客户端实例上的状态。

你可以说:

因此,每个任务文件都有自己的redis实例(这可能非常昂贵)。..。对于我们的系统,我们有超过12个任务文件遵循相同的模式,我注意到我们的请求变慢了。

几十个连接不太可能降低Redis服务器的速度。但是因为您的代码在幕后使用连接池,所以问题出在连接本身之外的某个地方。Redis是内存中的存储,因此在大多数可以想象的情况下都非常快。所以我更愿意在任务中寻找问题所在。

更新

来自@user3813256的评论。是的,他在任务级使用连接池。利用redis包的内置连接池的通常方式是共享连接。以最简单的方式,您的settings.py可能如下所示:

代码语言:javascript
复制
import redis

connection = None

def connect_to_redis():
    global connection
    connection = redis.StrictRedis(host='localhost', port=6379, db=0)

然后在应用程序的引导过程中调用connect_to_redis。然后在任务模块中使用导入connection

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31663288

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档