0

我想将 'Last Seen' 20 个请求的列表保留在 Django 视图中。我还想避免为它创建一个单独的模型,而只是将请求的 url 保存在 memcached 中,方法是将每个新请求推送到固定大小的队列,然后在视图中检索队列。但由于缓存只是键:值字典我想知道如何最好地实现这一点?

4

1 回答 1

1

使用 memcache 执行此操作的一种方法是将腌制的 Python 对象作为单个键存储在缓存中。

在这种情况下,我们可以使用 Python双端队列,它具有我们想要的 20 个最新项目列表的属性

每次我们记录一个新的页面视图时,我们都需要更新双端队列,这意味着获取它、取消腌制它、附加、腌制它并将新值设置回 memcache。

幸运的是,Django 的缓存框架将为我们处理酸洗和解酸。然而,我们需要注意的一件事是竞争条件的可能性 - 换句话说,如果另一个进程在我们获得副本之后并且在我们有机会将其设置回缓存之前也更新了双端队列。

出于这个原因,我们应该使用 memcache 的CAS('compare-and-set')操作。有一个扩展的 Django 缓存后端,可以在此处使用 CAS:
https ://github.com/anentropic/django-cas-cache

pip install django-cas-cache

我们在自定义 Django中间件中有一些代码来更新每个页面视图的缓存,大致如下所示:

中间件.py

from collections import deque
from django.core.cache import cache

class LastSeenMiddleware(object):
    def process_response(request, response):
        # you might want some logic like this to only
        # record successful requests
        if response.status != 200:
            return response

        # in case we don't already have a deque, try to add
        # (add will not overwrite if key already exists)
        added = cache.add('last_seen', deque([request.path], maxlen=20))

        if not added:
            def update(val):
                val.append(request.path)
                return val

            cache.cas('last_seen', update)

        return response

视图.py

from django.core.cache import cache
from django.shortcuts import render_to_response

def myview(request):
    last_seen = cache.get('last_seen')
    # whatever
    return render_to_response('mytemplate.html', {'last_seen': last_seen})

设置.py

CACHES = {
    'default': {
        'BACKEND': 'cascache.backends.memcached.MemcachedCASCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

# as a response processor, our middleware should probably come
# first in this list, in order to run *last*
MIDDLEWARE_CLASSES = (
    'myapp.middleware.LastSeenMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)
于 2015-10-19T17:40:43.090 回答