'Correct Way of using Redis Connection Pool in Python
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?
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?
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())
Solution 1:[1]
A1: Yes, they use the same connection pool.
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(metaclass=Singleton):
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)
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)
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]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Gerrat |