Opened 15 months ago
Last modified 8 months ago
#35651 assigned Bug
django redis cache not really using connection pooling — at Initial Version
| Reported by: | gojuukaze | Owned by: | |
|---|---|---|---|
| Component: | Core (Cache system) | Version: | 5.0 |
| Severity: | Normal | Keywords: | asgi, async |
| Cc: | Andrew Godwin, Carlton Gibson, Jon Janzen | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | no |
Description
I'm using django.core.cache.backends.redis.RedisCache as a backend for redis, and I recently observed that the number of Redis connections has been continuously increasing.
After debugging, I found that whenever the cache method is called, the RedisCacheClient class is reinitialized, and in the __init__ function of RedisCacheClient, the connection pool is set to empty.
This causes the _get_connection_pool method of RedisCacheClient to always create a new connection pool instead of using the existing one.
class RedisCacheClient:
def __init__(
self,
servers,
serializer=None,
pool_class=None,
parser_class=None,
**options,
):
import redis
self._lib = redis
self._servers = servers
self._pools = {} # << === set pools
def _get_connection_pool(self, write):
index = self._get_connection_pool_index(write)
#
# self._pools is is always empty.
#
if index not in self._pools:
self._pools[index] = self._pool_class.from_url(
self._servers[index],
**self._pool_options,
)
return self._pools[index]
One solution is to put _pools outside of __init__ , for example:
class RedisCacheClient:
# init pool
_pools = {}
def __init__(
self,
servers,
serializer=None,
pool_class=None,
parser_class=None,
**options,
):
import redis
self._lib = redis
self._servers = servers
## self._pools={}
By the way, I am using Django 5.0.7 and running it in asynchronous mode.