Django缓存使用初探

对于Web服务来说,对客户端发来的每个请求都需要计算,如果在短时间内有多个相同的请求,就要进行多次不必要的重复计算,使用缓存能有效地解决这个问题,如果请求的值存在缓存中,就直接返回缓存的值而不需要计算,能够减少计算和时延。

缓存位置

缓存数据可以存放在数据库,文件系统或内存中,使用缓存服务器还能实现多个服务器共享缓存,参考官方文档在settings.py中配置缓存。

Django默认配置了本地缓存,该缓存是多进程的,且线程安全。

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
    }
}

如果只有一本地内存缓存,可以省略LOCTION配置,如果有多个,则至少要给其中一个配置LOCATION以区分。

需要注意的是,Django是多进程部署时,每个进程都有自己私有的缓存实例,意味着跨缓存是不可能发生的,这样降低了命中率,而且如果其中一个进程修改了数据,其他进程的缓存没有更新之前就会返回错误的数据。

缓存粒度

Django提供了不同级别的缓存粒度,可以缓存整个站点、特定视图或部分难生成的内容,参考官方文档

视图缓存

django.views.decorators.cache定义了一个cache_page装饰器,用于自动缓存视图的响应。

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request):
    ...

cache_page的参数指定了缓存过期时间,以秒为单位。

如果多个URL指向相同的视图,每个URL将被单独缓存,如果URLconf是这样的:

urlpatterns = [
    path('foo/<int:code>/', my_view),
]

那么/foo/1//foo/23/的请求将被分别缓存。

但这种给my_view函数加装饰器的方法改变了函数,使my_view函数难以复用,可以改成在URLconf中再加cache_page装饰器。

from django.views.decorators.cache import cache_page

urlpatterns = [
    path('foo/<int:code>/', cache_page(60 * 15)(my_view)),
]

任意级别粒度

Django提供了底层的缓存API,用于缓存任意级别粒度的对象,可以缓存任何可以安全的 pickle的Python对象:字符串、字典、列表,或者其他。

使用django.core.cache.cache引用缓存,基本用法:

from django.core.cache import cache

# cache.set(key, value, timeout=DEFAULT_TIMEOUT, version=None)
cache.set('my_key', 'hello, world!', 30)

# cache.get(key, default=None, version=None)
cache.get('my_key')
# 'hello, world!'

# 30秒后'my_key'过期
cache.get('my_key')
# None

cache.get()可以带一个默认参数。如果对象不在缓存中,将返回指定的值。

cache.get('my_key', 'has expired')
# 'has expired'

在键不存在的时候,使用add()方法可以添加键。它与set()带有相同的参数,但如果指定的键已经存在,将不会尝试更新缓存。

如想知道通过add()存储的值是否在缓存中,可以检查返回值。如果值已保存,将返回 True,否则返回False

# cache.add(key, value, timeout=DEFAULT_TIMEOUT, version=None)
cache.set('add_key', 'Initial value')
cache.add('add_key', 'New value')
cache.get('add_key')
# 'Initial value'

如果想得到键值或者如果键不在缓存中时设置一个值,可以使用get_or_set()方法。它带有和get()一样的参数,但默认是为那个键设置一个新缓存值,而不是简单返回:

# cache.get_or_set(key, default, timeout=DEFAULT_TIMEOUT, version=None)

cache.get('my_new_key')  # returns None
cache.get_or_set('my_new_key', 'my new value', 100)
# 'my new value'

# 可以传递任何可调用的值作为默认值:
import datetime
cache.get_or_set('some-timestamp-key', datetime.datetime.now)
# datetime.datetime(2014, 12, 11, 0, 15, 49, 457920)

get_many()接口,对多个值返回一个字典。

# cache.get_many(keys, version=None)
cache.set('a', 1)
cache.set('b', 2)
cache.set('c', 3)
cache.get_many(['a', 'b', 'c'])
# {'a': 1, 'b': 2, 'c': 3}

set_many()传递键值对的字典,可以设置多个值。

# cache.set_many(dict, timeout)¶
cache.set_many({'a': 1, 'b': 2, 'c': 3})
cache.get_many(['a', 'b', 'c'])
# {'a': 1, 'b': 2, 'c': 3}

delete()清除特定对象缓存。

# cache.delete(key, version=None)
cache.delete('a')

delete_many()一次性清除多个键。

# cache.delete_many(keys, version=None)
cache.delete_many(['a', 'b', 'c'])

使用cache.clear()可以删除缓存里的所有键。

cache.touch()为键设置一个新的过期时间。

# cache.touch(key, timeout=DEFAULT_TIMEOUT, version=None)
cache.touch('a', 10)
# True

分别使用incr()decr()可以递增或递减一个已经存在的键的值。是否为原子方法依赖于后端支持。

# cache.incr(key, delta=1, version=None)
# cache.decr(key, delta=1, version=None)
cache.set('num', 1)
cache.incr('num')
# 2
cache.incr('num', 10)
# 12
cache.decr('num')
# 11
cache.decr('num', 5)
# 6

如果缓存后端已经实现了close()方法,可以用cache.close()关闭和缓存的连接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django 缓存可以用于存储一些计算结果、数据库查询结果、模板渲染结果等,从而避免重复计算、查询数据库等操作,提高应用性能。下面是一些 Django 缓存使用场景及示例: 1. 存储计算结果 如果应用中有一些计算操作比较耗时,可以将计算结果存储到缓存中,下次需要使用时直接从缓存中获取,避免重复计算。例如: ``` python from django.core.cache import cache def get_fibonacci_num(n): if n < 2: return n else: key = 'fibonacci_{}'.format(n) result = cache.get(key) if result is not None: return result else: result = get_fibonacci_num(n-1) + get_fibonacci_num(n-2) cache.set(key, result) return result ``` 以上代码使用缓存存储了斐波那契数列的计算结果,避免了重复计算。 2. 存储数据库查询结果 如果应用中有一些查询操作比较耗时,可以将查询结果存储到缓存中,下次需要使用时直接从缓存中获取,避免重复查询数据库。例如: ``` python from django.core.cache import cache from myapp.models import Post def get_latest_posts(): key = 'latest_posts' result = cache.get(key) if result is not None: return result else: result = Post.objects.order_by('-pub_date')[:10] cache.set(key, result) return result ``` 以上代码使用缓存存储了最新的 10 篇文章的查询结果,避免了重复查询数据库。 3. 存储模板渲染结果 如果应用中有一些模板渲染操作比较耗时,可以将模板渲染结果存储到缓存中,下次需要使用时直接从缓存中获取,避免重复渲染。例如: ``` python from django.core.cache import cache from django.template.loader import render_to_string def render_latest_posts(): key = 'latest_posts_html' result = cache.get(key) if result is not None: return result else: posts = get_latest_posts() result = render_to_string('latest_posts.html', {'posts': posts}) cache.set(key, result) return result ``` 以上代码使用缓存存储了最新文章的 HTML 渲染结果,避免了重复渲染。 注意:使用缓存可以提高应用性能,但是需要注意缓存的更新和失效机制,避免使用过期的缓存数据。同时,也需要根据实际情况进行选择和优化,避免缓存占用过多的内存等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值