缓存装饰器和django缓存后端,具有高级失效能力和防止狗群效应
项目描述
django-cache-utils提供了一些工具,使缓存相关工作更简单
cached 装饰器。它可以应用于函数、方法或类方法,并可以与任何django缓存后端(内置或第三方如django-newcache)一起使用。
支持对精确参数集(任何后端)进行细粒度失效,以及批量缓存失效(仅限group_backend)。缓存键是可读的,因为它们是由可调用对象的全名和参数构成的,然后进行清理以使memcached满意。
包装的可调用对象获得 invalidate 方法。使用与函数相同的参数调用 invalidate,则这些参数的缓存结果将被失效。
group_backend。这是一个具有组O(1)失效能力的django memcached缓存后端,使用MintCache算法防止狗群效应,并支持项目版本以允许优雅的更新和多个django项目在同一个memcached实例上。长键(>250)将自动截断并附加md5哈希。
安装
pip install django-cache-utils
然后(可选)
# settings.py CACHE_BACKEND = 'cache_utils.group_backend://:11211/'
用法
cached 装饰器可以与任何django缓存后端(内置或第三方如django-newcache)一起使用
from cache_utils.decorators import cached
@cached(60)
def foo(x, y=0):
print 'foo is called'
return x+y
foo(1,2) # foo is called
foo(1,2)
foo(5,6) # foo is called
foo(5,6)
foo.invalidate(1,2)
foo(1,2) # foo is called
foo(5,6)
foo(x=2) # foo is called
foo(x=2)
class Foo(object):
@cached(60)
def foo(self, x,y):
print "foo is called"
return x+y
obj = Foo()
obj.foo(1,2) # foo is called
obj.foo(1,2)
使用group_backend,cached 装饰器支持批量O(1)失效
from django.db import models
from cache_utils.decorators import cached
class CityManager(models.Manager):
# cache a method result. 'self' parameter is ignored
@cached(60*60*24, 'cities')
def default(self):
return self.active()[0]
# cache a method result. 'self' parameter is ignored, args and
# kwargs are used to construct cache key
@cached(60*60*24, 'cities')
def get(self, *args, **kwargs):
return super(CityManager, self).get(*args, **kwargs)
class City(models.Model):
# ... field declarations
objects = CityManager()
# an example how to cache django model methods by instance id
def has_offers(self):
@cached(30)
def offer_count(pk):
return self.offer_set.count()
return history_count(self.pk) > 0
# cache the function result based on passed parameter
@cached(60*60*24, 'cities')
def get_cities(slug)
return City.objects.get(slug=slug)
# cache for 'cities' group can be invalidated at once
def invalidate_city(sender, **kwargs):
cache.invalidate_group('cities')
pre_delete.connect(invalidate_city, City)
post_save.connect(invalidate_city, City)
注意
如果装饰的函数返回None,则将绕过缓存。
如果向“cached”装饰器传递了“group”参数,django-cache-utils将使用2次从memcached读取来获取值
@cached(60)
def foo(param)
return ..
@cached(60, 'my_group')
def bar(param)
return ..
# 1 read from memcached
value1 = foo(1)
# 2 reads from memcached + ability to invalidate all values at once
value2 = bar(1)
运行测试
cd test_project ./runtests.py