在Python中使用Redis连接池的正确方法 [英] Correct Way of using Redis Connection Pool in Python
问题描述
两个不同的模块 foo.py
和 bar.py
应该如何从Redis连接池中获得连接?换句话说,我们应该如何构建应用程序?
How should two different modules foo.py
and bar.py
get a connection from a Redis connection pool? In other words, how should we structure the app?
我相信目标是只有一个连接池,所有模块都可以从中获得连接。
I believe the goal is to have just a single connection pool for all modules to get a connection from.
第一季度:在我的示例中,两个模块是否都从同一连接池获得连接?
Q1: In my example, does both modules get a connection from the same connection pool?
第二季度:是否可以在 RedisClient.py
中创建RedisClient实例,然后将该实例导入其他2个模块中?还是有更好的方法?
Q2: Is it Ok to create the RedisClient instance in RedisClient.py
, then import the instance into the other 2 modules? Or is there a better way?
第三季度:是 conn
的延迟加载吗?实例变量实际上有用吗?
Q3: Is lazy loading of the conn
instance variable actually useful?
RedisClient.py
import redis
class RedisClient(object):
def __init__(self):
self.pool = redis.ConnectionPool(host = HOST, port = PORT, password = PASSWORD)
@property
def conn(self):
if not hasattr(self, '_conn'):
self.getConnection()
return self._conn
def getConnection(self):
self._conn = redis.Redis(connection_pool = self.pool)
redisClient = RedisClient()
foo.py
from RedisClient import redisClient
species = 'lion'
key = 'zoo:{0}'.format(species)
data = redisClient.conn.hmget(key, 'age', 'weight')
print(data)
bar.py
from RedisClient import redisClient
print(redisClient.conn.ping())
还是更好?
Or is this better?
RedisClient.py
import redis
class RedisClient(object):
def __init__(self):
self.pool = redis.ConnectionPool(host = HOST, port = PORT, password = PASSWORD)
def getConnection(self):
return redis.Redis(connection_pool = self.pool)
redisClient = RedisClient()
foo.py
from RedisClient import redisClient
species = 'lion'
key = 'zoo:{0}'.format(species)
data = redisClient.getConnection().hmget(key, 'age', 'weight')
print(data)
bar.py
from RedisClient import redisClient
print(redisClient.getConnection().ping())
推荐答案
A1:是的,他们使用相同的连接池。
A1: Yes, they use the same connection pool.
A2:这不是一个好习惯。由于您无法控制此实例的初始化。
A2: This isn't a good practice. As you cannot control the initialization of this instance. An alternative could be use singleton.
import redis
class Singleton(type):
"""
An metaclass for singleton purpose. Every singleton class should inherit from this class by 'metaclass=Singleton'.
"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class RedisClient(object):
def __init__(self):
self.pool = redis.ConnectionPool(host = HOST, port = PORT, password = PASSWORD)
@property
def conn(self):
if not hasattr(self, '_conn'):
self.getConnection()
return self._conn
def getConnection(self):
self._conn = redis.Redis(connection_pool = self.pool)
然后 RedisClient
将是一个单例类。不管您调用 client = RedisClient()
多少次,您都会得到相同的对象。
Then RedisClient
will be a singleton class. Not matter how many times you call client = RedisClient()
, you will get the same object.
所以您可以像这样使用它:
So you can use it like:
from RedisClient import RedisClient
client = RedisClient()
species = 'lion'
key = 'zoo:{0}'.format(species)
data = client.conn.hmget(key, 'age', 'weight')
print(data)
第一次调用 client = RedisClient()
实际上将初始化该实例。
And the first time you call client = RedisClient()
will actually initialize this instance.
或者您可能希望根据不同的参数获取不同的实例:
Or you may want to get different instance based on different arguments:
class Singleton(type):
"""
An metaclass for singleton purpose. Every singleton class should inherit from this class by 'metaclass=Singleton'.
"""
_instances = {}
def __call__(cls, *args, **kwargs):
key = (args, tuple(sorted(kwargs.items())))
if cls not in cls._instances:
cls._instances[cls] = {}
if key not in cls._instances[cls]:
cls._instances[cls][key] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls][key]
这篇关于在Python中使用Redis连接池的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!