用装饰器优化Redis缓存代码

  • 发布时间:2017年4月28日 09:41
  • 作者:杨仕航
  • 分类标签: Django
  • 阅读(8264)
  • 评论(2)

使用Redis缓存提速的效果不错,但回顾代码发现有不少冗余和麻烦的地方。

每一个需要使用缓存的数据,我都写一个方法获取数据,再写一个方法处理缓存。如下代码:

#coding:utf-8
from django.core.cache import cache
import time

#获取readed缓存
def get_readed_cache():
    #判断键是否存在
    key = 'readed'
    if cache.has_key(key):
        data = cache.get(key)
    else:
        #不存在,则获取数据,并写入缓存
        data = get_readed_data()
 
        #写入缓存
        cache.set(key, data, 3600-int(time.time() % 3600))
    return data
    
#获取readed数据
def get_readed_data():
    #获取相关数据,这里省略
    data = ''
    return data


使用的时候,直接调用get_readed_cahce方法即可。但这么一来,若需要用到缓存的地方越来越多。每一个都需要这么写一套代码。而其中每个获取缓存的方法都很固定,都是判断键值是否存在。若存在则返回缓存中的数据;若不存在则获取数据再写入缓存。不同的地方是键值、写入缓存超时的时间和获取数据的方法。

重复类似的代码将被写很多遍。这很明显可以将获取缓存的数据写成一个带参数的装饰器。可将键值和超时时间作为装饰器的参数。如下代码:

#coding:utf-8
from django.core.cache import cache

#获取redis缓存的装饰器
def redis_cache(key, timeout):
    def __redis_cache(func):
        def warpper(*args, **kw):
            #判断缓存是否存在
            if cache.has_key(key):
                data = cache.get(key)
            else:
                #若不存在则执行获取数据的方法
                #注意返回数据的类型(字符串,数字,字典,列表均可)
                data = func(*args, **kw)
                cache.set(key, data, timeout)
            return data
        return warpper
    return __redis_cache


为了方便测试,可加入print输出信息,观察执行过程。

#coding:utf-8
from django.core.cache import cache

#获取redis缓存的装饰器
def redis_cache(key, timeout):
    def __redis_cache(func):
        def warpper(*args, **kw):
            #判断缓存是否存在
            print('check key: %s' % key)
            if cache.has_key(key):
                print('get cache')
                data = cache.get(key)
            else:
                #若不存在则执行获取数据的方法
                #注意返回数据的类型(字符串,数字,字典,列表均可)
                print('get data')
                data = func(*args, **kw)
                print('set cache')
                cache.set(key, data, timeout)
            return data
        return warpper
    return __redis_cache


使用装饰器方法如下:

#键值为test,超时时间为60秒
@redis_cache('test', 60)
def get_test_data():
    # 获取Blog模型随机排序前3条数据
    # (Blog模型是我自己的模型,具体代码根据自己需求获取数据)
    # values执行结果,将返回一个字典。字典可以直接存入redis
    data = Blog.objects.values('id', 'caption').order_by('?')[:3]
    return data


进入django shell后台,第1次执行get_test_data方法。

20170428/20170428093251948.png


由于从未执行过该方法,没有键值为test的缓存数据。则执行被加装饰器的方法,获取具体的数据。再执行1次get_test_data方法。

20170428/20170428093551410.png


第2次执行,检查发现有缓存,则直接获取缓存,不执行获取数据的方法。

你可以等60秒后,再执行一次get_test_data方法。由于设置缓存超时时间为60秒,该缓存将被清除。再执行一次方法将会重新获取数据,写入缓存。

测试执行无误,可将装饰器单独放到一个Python脚本文件,以供Django或其他Web、脚本等使用。

上一篇:VSTO加载xlam和调用vba的方法

下一篇:QuerySet查询优化

相关专题: Django+Celery+Redis   

评论列表

itbj

itbj

🇨🇳😀

2017-05-14 02:36 回复

fjkang

fjkang

👍学习了

2018-07-06 09:43 回复

新的评论

清空