当前位置: 首页 > news >正文

Django 缓存框架

动态网站的一个基本权衡是它们是动态的。每当用户请求页面时,Web 服务器进行各种计算,从数据库查询到模板渲染到业务逻辑,以创建您网站访问者看到的页面。从处理开销的角度来看,这比标准的从文件系统中读取文件的服务器安排要昂贵得多。

对于大多数 Web 应用程序,这种开销并不是什么大问题。大多数 Web 应用程序不像 washingtonpost.com 或 slashdot.org 那样大型,它们是小到中等规模的站点,流量一般。但对于中等到高流量的站点来说,尽量减少开销是非常重要的。

这就是缓存的用武之地。

缓存是指保存昂贵计算的结果,以便下次无需再次执行计算。以下是一些伪代码,说明了如何为动态生成的网页实现缓存:

given a URL, try finding that page in the cache
if the page is in the cache:return the cached page
else:generate the pagesave the generated page in the cache (for next time)return the generated page

Django 自带强大的缓存系统,可以让你保存动态页面,这样就不必为每次请求计算。为了方便,Django 提供了不同级别的缓存粒度。你可以缓存特定视图的输出,你可以只缓存难以生成的部分,或者你可以缓存整个网站。

Django 也与 "下游" 缓存很好地配合,​ 比如 Squid 和基于浏览器的缓存。这些是您不直接控制但可以通过 HTTP 标头提供提示的缓存类型,用于指示哪些部分的网站应该被缓存,以及如何缓存。

一、设置缓存

缓存系统需要少量的设置。也就是说,你必须告诉它你的缓存数据应该放在哪里 —— 是在数据库中,还是在文件系统上,或者直接放在内存中。这是一个重要的决定,会影响你的缓存的性能;是的,有些缓存类型比其他类型快。

你的缓存首选项在设置文件中的 CACHES 设置中。以下是所有可用值对 CACHES 的解释。

1、Memcached

Memcached 是一个完全基于内存的缓存服务器,最初是为了处理 LiveJournal.com 上的高负载而开发的,并随后由 Danga Interactive 开源。它被类似 Facebook 和 Wikipedia 这样的网站使用,以减少数据库访问并显著提高网站性能。

Memcached 以一个守护进程的形式运行,并且被分配了指定数量的 RAM。它所做的就是提供一个快速接口用于在缓存中添加,检索和删除数据。所有数据都直接存储在内存中,因此不会产生数据库或文件系统使用的开销。

在安装 Memcached 本身之后,您需要安装一个 Memcached 绑定。有几个 Python Memcached 绑定可用,Django 支持的两个是 pylibmc 和 pymemcache。

在 Django 中使用 Memcached :

  •  设置 BACKEND 为 django.core.cache.backends.memcached.PyMemcacheCache 或 django.core.cache.backends.memcached.PyLibMCCache (取决于你选择的 memcached 绑定)。
  • 将 LOCATION 设置为 ip:port 值,其中 ip 是 Memcached 守护进程的 IP 地址,port 是 Memcached 运行的端口,或者设置为 unix:path 值,其中 path 是 Memcached Unix socket 文件的路径。

在这个例子中,Memcached 运行在 localhost(127.0.0.1)端口 11211,使用 pymemcache 绑定:

CACHES = {"default": {"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache","LOCATION": "127.0.0.1:11211",}
}

在这个例子中,Memcached 可以通过本地 Unix 套接字文件 /tmp/memcached.sock 使用 pymemcache 绑定:

CACHES = {"default": {"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache","LOCATION": "unix:/tmp/memcached.sock",}
}

 Memcached 有一个很好的特性,就是它可以在多台服务器上共享一个缓存。这意味着你可以在多台机器上运行 Memcached 守护进程,程序将把这组机器作为一个 单一 的缓存,而不需要在每台机器上重复缓存值。要利用这个特性,请在 LOCATION 中包含所有服务器地址,可以是分号或逗号分隔的字符串,也可以是一个列表。

在这个例子中,缓存是通过运行在 IP 地址 172.19.26.240 和 172.19.26.242 上的 Memcached 实例共享的,这两个实例都在 11211 端口上:

CACHES = {"default": {"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache","LOCATION": ["172.19.26.240:11211","172.19.26.242:11211",],}
}

在下面的例子中,缓存是由运行在 IP 地址 172.19.26.240(端口11211)、172.19.26.242(端口11212)和 172.19.26.244(端口11213)上的 Memcached 实例共享的: 

CACHES = {"default": {"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache","LOCATION": ["172.19.26.240:11211","172.19.26.242:11212","172.19.26.244:11213",],}
}

默认情况下,PyMemcacheCache 后端设置以下选项(您可以在 OPTIONS 中覆盖它们):

"OPTIONS": {"allow_unicode_keys": True,"default_noreply": False,"serde": pymemcache.serde.pickle_serde,
}

关于 Memcached 的最后一点是,基于内存的缓存有一个缺点:因为缓存的数据存储在内存中,如果你的服务器崩溃,数据将丢失。显然,内存并不是用来永久存储数据的,所以不要依赖基于内存的缓存作为你唯一的数据存储。毫无疑问,Django 缓存后端中的 每个 都不应该用于永久存储 —— 它们的目的都是为了缓存的解决方案,而不是存储 —— 但我们在这里指出这一点是因为基于内存的缓存是格外临时的。

2、Redis

Redis 是一个内存数据库,可用于缓存。要开始使用它,您需要在本地或远程机器上运行一个 Redis 服务器。

在设置好 Redis 服务器之后,您需要安装 Redis 的 Python 绑定。Django 原生支持的绑定是 redis-py。同时,建议安装 hiredis-py 包。

要在 Django 中使用 Redis 作为缓存后端:

  • 将 BACKEND 设置为 django.core.cache.backends.redis.RedisCache。
  • 将 LOCATION 设置为指向您的 Redis 实例的 URL,使用适当的方案。

例如,如果 Redis 在本地主机(127.0.0.1)的端口 6379 上运行:

CACHES = {"default": {"BACKEND": "django.core.cache.backends.redis.RedisCache","LOCATION": "redis://127.0.0.1:6379",}
}

通常,Redis 服务器受到身份验证的保护。为了提供用户名和密码,您可以将它们与 URL 一起添加到 LOCATION 中:

CACHES = {"default": {"BACKEND": "django.core.cache.backends.redis.RedisCache","LOCATION": "redis://username:password@127.0.0.1:6379",}
}

如果您在复制模式下设置了多个 Redis 服务器,可以将这些服务器指定为分号或逗号分隔的字符串,或者作为一个列表。在使用多个服务器时,写操作将在第一个服务器(领导者)上执行,读操作将在随机选择的其他服务器(副本)上执行:

CACHES = {"default": {"BACKEND": "django.core.cache.backends.redis.RedisCache","LOCATION": ["redis://127.0.0.1:6379",  # leader"redis://127.0.0.1:6378",  # read-replica 1"redis://127.0.0.1:6377",  # read-replica 2],}
}
from django.core.cache import cache# 设置键值对(默认使用配置中的 TIMEOUT)
cache.set("user:1:name", "Alice")# 设置键值对并指定超时时间(单位:秒)
cache.set("user:1:email", "alice@example.com", timeout=3600)# 获取单个值
name = cache.get("user:1:name")  # 返回 "Alice"
email = cache.get("user:1:email")  # 返回 "alice@example.com"# 获取不存在的键(返回 None)
age = cache.get("user:1:age")  # 返回 None# 设置默认值(如果键不存在)
age = cache.get("user:1:age", default=25)  # 返回 25

 

 3、数据库缓存

Django 可以在数据库中存储缓存数据。如果你有一个快速、索引正常的数据库服务器,这种缓存效果最好。

用数据库表作为你的缓存后端:

  • 将 BACKEND 设置为 django.core.cache.backends.db.DatabaseCache
  • 将 LOCATION 设置为数据库表的 tablename。这个表名可以是没有使用过的任何符合要求的名称。

在这个例子中,缓存表的名称是 my_cache_table :

CACHES = {"default": {"BACKEND": "django.core.cache.backends.db.DatabaseCache","LOCATION": "my_cache_table",}
}

与其他缓存后端不同,数据库缓存不支持在数据库级别自动清除过期条目。相反,每次调用 add()set(), 或 touch() 时都会清除过期的缓存条目。

 创建缓存表

在使用数据库缓存之前,您必须使用以下命令创建缓存表:

python manage.py createcachetable

这将在数据库中创建一个表,该表的格式与 Django 数据库缓存系统期望的一致。该表的表名取自 LOCATION 。

如果你正在使用多个数据库缓存, createcachetable 会为每个缓存创建一个表。

如果你正在使用多个数据库, createcachetable 观察你的数据库路由器的 allow_migrate() 方法(见下文)。

像 migrate 一样, createcachetable 不会影响已经存在的表,它只创建缺失的表。

要打印即将运行的 SQL,而不是运行它,请使用 createcachetable --dry-run 选项。

多数据库

如果在多数据库中使用缓存,你也需要设置数据库缓存表的路由指令。因为路由的原因,数据库缓存表在 django_cache 应用程序中显示为 CacheEntry 的模型名。这个模型不会出现在模型缓存中,但模型详情可用于路由目的。

比如,下面的路由可以将所有缓存读取操作指向 cache_replica ,并且所有的写操作指向 cache_primary。缓存表将会只同步到 cache_primary

class CacheRouter:"""A router to control all database cache operations"""def db_for_read(self, model, **hints):"All cache read operations go to the replica"if model._meta.app_label == "django_cache":return "cache_replica"return Nonedef db_for_write(self, model, **hints):"All cache write operations go to primary"if model._meta.app_label == "django_cache":return "cache_primary"return Nonedef allow_migrate(self, db, app_label, model_name=None, **hints):"Only install the cache model on primary"if app_label == "django_cache":return db == "cache_primary"return None

如果你没有指定路由指向数据库缓存模型,缓存后端将使用 默认 的数据库。

如果没使用数据库缓存后端,则无需担心为数据库缓存模型提供路由指令。

4、文件系统缓存

基于文件的后端序列化并保存每个缓存值作为单独的文件。要使用此后端,可将 BACKEND 设置为 "django.core.cache.backends.filebased.FileBasedCache" 并将 LOCATION 设置为一个合适的路径。比如,在 /var/tmp/django_cache 存储缓存数据,使用以下配置:

CACHES = {"default": {"BACKEND": "django.core.cache.backends.filebased.FileBasedCache","LOCATION": "/var/tmp/django_cache",}
}

如果使用 Windows 系统,将驱动器号放在路径开头,如下:

CACHES = {"default": {"BACKEND": "django.core.cache.backends.filebased.FileBasedCache","LOCATION": "c:/foo/bar",}
}

目录路径应该是绝对路径——因此,它应该以文件系统根目录开始。无需担心是否需要以斜杠结尾。

确保该设置所指向的目录存在,并且具备读写权限,或者可以由您的 Web 服务器运行的系统用户创建。继续上面的示例,如果您的服务器以用户 apache 运行,请确保目录 /var/tmp/django_cache 存在,并且用户 apache 具备读写权限,或者可以由用户 apache 创建。

5、本地内存缓存

如果你的配置文件中没有指定其他缓存,那么这是默认的缓存。如果你想获得内存缓存的速度优势,但又不具备运行 Memcached 的能力,可以考虑使用本地内存缓存后端。这个缓存是每进程所有(见下文)和线程安全的。要使用它,可以将 BACKEND 设置为 "django.core.cache.backends.locmem.LocMemCache"。例如:

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


LOCATION 被用于标识各个内存存储。如果只有一个 locmem 缓存,你可以忽略 LOCATION 。但是如果你有多个本地内存缓存,那么你至少要为其中一个起个名字,以便将它们区分开。

这种缓存使用最近最少使用(LRU)的淘汰策略。

请注意,每个进程都会有自己的私有缓存实例,这意味着不可能进行跨进程缓存。这也意味着本地内存缓存的内存效率不是特别高,所以对于生产环境来说,它可能不是一个好的选择。对于开发来说是不错的选择。

相关文章:

  • 华为云空间安卓版存储扩展与文件管理体验测评
  • AI大模型学习十四、白嫖腾讯Cloud Studio AI环境 通过Ollama+Dify+DeepSeek构建生成式 AI 应用-接入DeepSeek大模型
  • 使用 ELK 实现全链路追踪:从零到一的实践指南
  • 阿里云服务器(ECS)基础指南:从入门到核心场景解析​
  • ubuntu新增磁盘挂载
  • Jackson 使用方法详解
  • 操作系统八股问——连载ing
  • 具身智能机器人的应用场景及最新进展
  • 解决MacOS端口被占用问题
  • 安卓基础(接口interface)
  • 高压场景首选:CKESC ROCK 120A-H CAN 电调技术解析与实测报告
  • 51c大模型~合集122
  • 第十六节:开放性问题-Vue与React Hooks对比
  • vue3:v-model的原理示例
  • ISO-C99标准 最小限定值
  • 驱动开发硬核特训 │ Regulator 子系统全解
  • IDEA2022.3开启热部署
  • 【React Native】精通 react native
  • 假云阴影模拟
  • 数字孪生三维建模+虚拟仿真,构建可预测的未来工厂
  • 美情报机构攻击中国大型商用密码产品提供商,调查报告公布
  • 广东一公司违规开展学科培训被罚没470万,已注销营业执照
  • 加拿大驾车撞人事件遇难人数升到11人
  • 国家核安全局局长:我国核电进入大规模建设高峰期,在建规模超其他国家总和
  • 我国对国家发展规划专门立法
  • 哈马斯官员:只要以军持续占领,哈马斯就不会放下武器