Monday, February 13, 2012

Using multi-cache backends in Django, and an issue in django-redis-cache

The missing Manual
  It seems something was missed in Django Document about the Cache. Django start support multi-caches since version 1.3, but in its document 1.3 (https://docs.djangoproject.com/en/1.3/topics/cache/) and Dev(https://docs.djangoproject.com/en/dev/topics/cache/), it didn't mentioned about how to do route between multi-caches at all.
  In the current document(https://docs.djangoproject.com/en/1.3/topics/cache/#the-low-level-cache-api), it introduced that there's a cache object already for default cache. 
"The cache module, django.core.cache, has a cache object that's automatically created from the 'default' entry in the CACHES setting: "
  I guess there's a existing route function for shifting between different cache backend, coz it mentioned about "created from default entry", I should be able to create one by other entry >.,< 
  And I found something as I wish:
   1: DEFAULT_CACHE_ALIAS = 'default'
   2:  
   3: cache = get_cache(DEFAULT_CACHE_ALIAS)

  This is the cache object using default backend. 
  Well, now, we've found the "get_cache" method is the missing stuff Smile with tongue out
Let's try it out, if we have following settings in <settings.py>


   1: CACHES = {
   2:     'default': {
   3:         'BACKEND': 'redis_cache.RedisCache',
   4:         'LOCATION': '192.168.32.139:6379',
   5:         'OPTIONS': {
   6:             'DB': 2,
   7:             #'PARSER_CLASS': 'redis.connection.HiredisParser',
   8:         }
   9:     },
  10:  
  11:     '2ndcache': {
  12:         'BACKEND': 'redis_cache.RedisCache',
  13:         'LOCATION': '192.168.32.139:6379',
  14:         'OPTIONS': {
  15:             'DB': 3,
  16:             #'PARSER_CLASS': 'redis.connection.HiredisParser',
  17:         },
  18:     }    
  19: }

code below in <views.py> or somewhere should save to different Redis db.


   1: cache.set('x',1) #default cache object, using redis db 2
   2: get_cache('2ndcache').set('x',2) #save to 2ndcache(radis db 3)

But, unfortunately, you will find that , both operations write value to redis db 2.

An issue in redis_cache

That's because there is a bug, maybe we should call it an issue, in redis_cache 0.9.2 which we used as cache backend for django to connect redis.

I've submit the issue to author, and a patch in the issue page.https://github.com/sebleier/django-redis-cache/issues/30
you can get issue fixed code here:
https://github.com/feifangit/django-redis-cache

find <cache.py> in your python library path. Maybe in XXX\Python26\Lib\site-packages\django_redis_cache-0.9.2-py2.6.egg\redis_cache

modify get_connection_pool method in class CacheConnectionPool as follows:


   1: class CacheConnectionPool(object):
   2:     _connection_pools = {} #id: reis.ConnectionPool
   3:  
   4:     def get_connection_pool(self, host='127.0.0.1', port=6379, db=1,
   5:         password=None, parser_class=None,
   6:         unix_socket_path=None):
   7:         if self._connection_pools.get(db) is None:
   8:             connection_class = (
   9:                 unix_socket_path and UnixDomainSocketConnection or Connection
  10:             )            
  11:             kwargs = {
  12:                 'db': db,
  13:                 'password': password,
  14:                 'connection_class': connection_class,
  15:                 'parser_class': parser_class,
  16:             }
  17:             if unix_socket_path is None:
  18:                 kwargs.update({
  19:                     'host': host,
  20:                     'port': port,
  21:                 })
  22:             else:
  23:                 kwargs['path'] = unix_socket_path
  24:             self._connection_pools[db] = redis.ConnectionPool(**kwargs)
  25:         return self._connection_pools.get(db)

2 comments:

  1. This was recently fixed in https://github.com/sebleier/django-redis-cache/commit/ab08444372b6514d2f08be31b43d5c4e52d4713f

    ReplyDelete
    Replies
    1. Yes, I see. Their action is too slow.

      Delete