簡體   English   中英

如何在redis中正確使用連接池?

[英]How do I properly use connection pools in redis?

我不清楚連接池如何工作,以及如何正確使用它們。 我希望有人可以詳細說明。 我在下面勾勒出我的用例:

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實例(可能非常昂貴)。 優化此過程的最佳方法是什么? 是否可以在此示例中使用連接池? 有沒有更有效的方法來設置這種模式?

對於我們的系統,我們有相同模式的十幾個任務文件,我注意到我們的請求減慢了。

謝謝

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服務器打開了多少連接。

您將使用基於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()

UPDATE

如果您的文件作為不同的進程運行,您將必須使用redis代理,它將為您匯集連接,而不是直接連接到redis,您將不得不使用代理。 一個非常穩定的redis(和memcached)代理是由twitter創建的twemproxy ,其主要目的是減少開放連接。

這是奶酪店頁面上的引用。

在幕后,redis-py使用連接池來管理與Redis服務器的連接。 默認情況下,您創建的每個Redis實例將依次創建自己的連接池 您可以通過將已創建的連接池實例傳遞給Redis類的connection_pool參數來覆蓋此行為並使用現有連接池。 您可以選擇執行此操作以實現客戶端分片,或者對如何管理連接進行更精細的控制。

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

而且,實例是線程安全的

可以在線程之間安全地共享Redis客戶端實例。 在內部,連接實例僅在命令執行期間從連接池中檢索,並在之后直接返回到池。 命令執行永遠不會修改客戶端實例上的狀態。

你說:

因此每個任務文件都有自己的redis實例(可能非常昂貴)。 ...對於我們的系統,我們有相同模式的十幾個任務文件,我注意到我們的請求減慢了。

幾十個連接幾乎不可能減慢Redis服務器的速度。 但是因為你的代碼在幕后使用了連接池,所以問題就在於連接本身。 Redis是內存存儲,因此在大多數可以想象的情況下都非常快。 所以我寧願在任務中尋找問題。

更新

來自@ user3813256的評論。 是的,他在任務級別使用連接池。 利用redis包內置連接池的redis方法就是共享連接。 最簡單的方法是,您的settings.py可能如下所示:

import redis

connection = None

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

然后在應用程序的引導程序中的某處調用connect_to_redis 然后在任務模塊中使用導入connection

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM