缓存装饰器和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://localhost: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