首页 > 解决方案 > 即使有空的 redis 键,Django REST 框架仍然会响应缓存数据

问题描述

上下文:我在ModelViewSet使用方法 decorator 通过 Django REST 框架 (DRF) 中的 redis API 视图进行缓存时遇到问题cache_page

文档参考:https ://www.django-rest-framework.org/api-guide/caching/

代码片段:https ://hastebin.com/apoqeloyav.py

示例场景

这是当前行为(使用 Swagger UI 手动测试)

  1. 将 GET 请求发送到 /products 端点 -> 这将请求我的 DRF 服务器并缓存视图

  2. 再次向 /products 端点发送 GET 请求 -> 这会将产品数据作为缓存数据响应(已在开发工具网络选项卡“从磁盘缓存提供服务”中验证)。这也意味着它没有访问我的 DRF 服务器来检索数据。

  3. 向 /products/{product_id} 端点发送 PATCH 请求 -> 这将更新详细信息然后使缓存无效(此时 Redis 缓存键为空)

  4. 再次向 /products 端点发送 GET 请求 ->这仍会将产品数据作为缓存数据响应(已验证,因为执行步骤 3 的更新数据仍然不存在)。这也意味着它没有访问我的 DRF 服务器来检索数据。

在此处输入图像描述

这是我的预期行为(使用 Swagger UI 手动测试)

  1. 将 GET 请求发送到 /products 端点 -> 这将请求我的 DRF 服务器并缓存视图
  2. 再次向 /products 端点发送 GET 请求 -> 这会将产品数据作为缓存数据响应(已在开发工具网络选项卡“从磁盘缓存提供服务”中验证)。这也意味着它没有访问我的 DRF 服务器来检索数据。
  3. 向 /products/{product_id} 端点发送 PATCH 请求 -> 这将更新详细信息然后使缓存无效(此时 Redis 缓存键为空)
  4. 再次向 /products 端点发送 GET 请求 ->这应该响应来自数据库的产品数据。这意味着它会访问我的 DRF 服务器以检索更新的数据。

如何获得预期的结果,以便如果 redis 缓存为空,它应该访问我的 DRF 服务器以检索最新数据并缓存后续调用,直到它再次失效?另外,我不确定这是一个问题,还是只是正常行为。

到目前为止,这是我在使 redis 中的缓存数据无效时尝试的方法,但它们都不起作用并且仍然提供缓存数据

  1. 将缓存过期设置为 0
  2. 将缓存值设置为无
  3. 以编程方式删除所有键
  4. 通过 redis-cli 删除所有密钥
  5. 关闭 redis-server -> 但仍然服务from disk cache并且没有命中我的 DRF API 端点

这是我正在使用的版本

标签: cachingdjango-rest-frameworkredis

解决方案


来自 4. 的请求甚至没有命中 redis 缓存,因为它返回了本地缓存(请注意响应代码中的“来自磁盘缓存”)。

您应该区分公共缓存(即所有用户使用的服务器缓存)和私有缓存(用户的浏览器缓存)。

我认为,在使用cache_page装饰器时,除了缓存请求之外,它还设置“缓存控制”响应标头以允许请求的私有缓存。浏览器使用这些标头在本地缓存请求,并返回本地缓存的响应,直到max-age过期。

为了防止这种行为,在服务器级别,您可以使用@never_cache装饰器,它设置Cache-control响应标头以防止本地缓存,或者使用@cache_control(public=True)仅允许请求的公共缓存(这也相应地调整缓存控制响应标头)。

更多关于控制缓存


推荐阅读