3

我有一个查询,结果每天只更改一次。我为该页面收到的每个请求都执行该查询似乎是一种浪费。我正在研究为此使用 memcached。

我将如何开始?任何人在使用 Django 的缓存时应该避免任何建议或陷阱?我应该缓存在模板还是视图中?

这个问题可能看起来很模糊,但这只是因为我以前从未处理过缓存。所以如果有什么我可以详细说明的,尽管问。

细化

根据 Ken Cochrane:

  1. 此数据多久更改一次:相关数据将在该日历日期锁定。因此,例如,我将提取 2011 年 1 月 30 日的数据,并且我可以整天提供该缓存副本,直到 2011 年 1 月 31 日它会被刷新。

  2. 我是否在不止一个地方使用此数据:仅在一个视图中。

  3. 将有多少数据:平均 10 个模型对象,其中包含大约 15 个字段,其中最大的是CharField(max_length=120). 我会将字段数量减少values()到其中的一半左右。

4

3 回答 3

9

通常在我决定在哪里进行缓存之前,我会问自己几个问题。

  1. 此数据多久更改一次
  2. 我是否在不止一个地方使用这些数据
  3. 会有多少数据

由于我不知道您的应用程序的所有细节,我将做一些假设。

  1. 您有一个视图,该视图要么接受日期,要么使用当前日期来查询数据库以提取该日期的所有日历事件。
  2. 您只在一个模板上显示此信息,
  3. 数据量不太大(少于 100 个条目)。

有了这些假设,您有 3 个选项。1. 缓存模板 2. 缓存视图 3. 缓存查询集

通常,当我进行缓存时,我会缓存查询集,这使我可以更好地控制我想要如何缓存数据,并且我可以在多个地方重用相同的缓存数据。

我发现缓存查询集的最简单方法是在 ModelManger 中为相关模型执行此操作。我会创建一个像 get_calender_by_date(date) 这样的方法来为我处理查询和缓存。这是一个粗略的模型

CACHE_TIMEOUT_SECONDS = 60 * 60 * 24 # this is 24 hours

class CalendarManager(models.Manager):

    def get_calendar_by_date(self, by_date):
        """ assuming date is a datetime object """
        date_key = by_date.strftime("%m_%d_%Y")
        cache_key = 'CAL_DATE_%s' % (date_key)
        cal_date = cache.get(cache_key)
        if cal_date is not None:
            return cal_date

        # not in cache get from database
        cal_date = self.filter(event_date=by_date)

        # set cal_date in cache for later use
        cache.set(cache_key, cal_date, CACHE_TIMEOUT_SECONDS)
        return cal_date

缓存时需要注意的一些事项

  1. 确保您存储在缓存中的对象可以腌制
  2. 由于 memcache 不知道今天是哪一天,因此您需要确保不会过度缓存。例如,如果它是 1 月 21 日中午并且您缓存了 24 小时,则该日历信息将显示到 1 月 22 日中午,这可能不是您要查找的内容,因此请确保您在设置查询时间时要么将其设置为一个较小的值,以便它更快地过期,要么您计算缓存多长时间,以便它在您希望它过期时过期。
  3. 确保您知道要缓存的对象的大小。如果你的 memcache 实例只有 16MB 的存储空间,但你想存储 32MB 的数据,那么缓存对你没有多大用处。

缓存模板或视图时,您需要注意以下事项

  1. 设置您的缓存超时,使其不会太大,我认为您不能以编程方式更改模板缓存超时,并且它是硬编码的,因此如果您将其设置得太高,您最终会得到一个页面日期。您应该能够以编程方式更改缓存时间,因此更安全一些。
  2. 如果您正在缓存模板并且模板上的其他信息是动态的并且一直在变化,请确保您只将缓存标记放在您想要缓存一段时间的页面部分周围。如果你把它放在错误的地方,你可能会得到错误的结果。

希望这可以为您提供足够的信息来开始。祝你好运。

于 2011-01-30T15:33:47.283 回答
1

首先尝试阅读此内容。Django 有能力 {% cache for_seconds something %} 只需使用缓存标签。 http://docs.djangoproject.com/en/dev/topics/cache/

于 2011-01-27T16:59:55.663 回答
0

您可以使用 Python 的 builtin 按日期缓存函数的结果lru_cache,只要方法参数是普通的“2021-09-22”日期而不是时间戳:

import datetime
from functools import lru_cache

@lru_cache(maxsize=1)
def my_func(date: datetime.date):
    if type(date) is not datetime.date:
        raise ValueError(f"This method is cached by calendar date, but received date {date}.")
于 2021-09-22T15:17:00.087 回答