获取 Django 中的缓存键列表



我试图理解 Django 如何为我的视图设置键。我想知道是否有办法从Memcached获取所有保存的密钥。像cache.all()之类的东西。我一直在尝试找到带有cache.has_key('test')键,但仍然无法弄清楚视图键是如何命名的。

更新:我需要这个的原因是因为我需要手动删除部分缓存,但不知道 Django 为我的cache_view键设置的键值

对于 RedisCache,您可以使用 获取所有可用的密钥。

from django.core.cache import cache
cache.keys('*')

如前所述,无法获取 django 中所有缓存键的列表。如果您使用的是外部缓存(例如内存缓存或数据库缓存(,则可以直接检查外部缓存。

但是如果你想知道如何将 django 密钥转换为后端系统中使用的密钥,django 的 make_key(( 函数会做到这一点。

https://docs.djangoproject.com/en/1.8/topics/cache/#cache-key-transformation

>>> from django.core.cache import caches
>>> caches['default'].make_key('test-key')
u':1:test-key'

对于调试,您可以暂时切换到 LocMemCache 而不是 PyMemcacheCache

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

然后看到这个问题:

from django.core.cache.backends import locmem
print(locmem._caches)

对于 Redis 后端

我将添加这个答案,因为我登陆了这个 SO 问题,搜索完全相同的问题但使用不同的缓存后端。此外,对于 REDIS,特别是如果您为多个应用程序使用相同的 REDIS 服务器,您将需要使用 KEY_PREFIX 选项来限定缓存键的范围,否则您最终可能会得到来自另一个应用程序的缓存键。

我的答案是,如果您在settings.py中设置了KEY_PREFIX,并且使用的是redis_cache.RedisCachedjango.core.cache.backends.redis.RedisCache

例如

 CACHES = {
    "default": {
        "BACKEND": "redis_cache.RedisCache",
        "LOCATION": f"redis://localhost:6379",
        "KEY_PREFIX": "my_prefix",
    },
 }

 CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": f"redis://localhost:6379",
        "KEY_PREFIX": "my_prefix",
    },
 }

redis_cache.RedisCache

from django.conf import settings
from django.core.cache import cache
cache_keys = cache.get_client(1).keys(
   f"*{settings.CACHES['default']['KEY_PREFIX']}*"
)

django.core.cache.backends.redis.RedisCache

做一些测试表明,使用 Django 内置的 RedisCache 可能已经限定了范围,但就我而言,我这样做是明确的。 调用.keys("*")还将返回属于芹菜任务的键

from django.conf import settings
from django.core.cache import cache
cache_keys = cache._cache.get_client().keys(
    f"*{settings.CACHES['default']['KEY_PREFIX']}*"
)

奖励:删除所有应用程序密钥

如果你想清除特定应用程序的缓存而不是 REDIS 中的所有键,你需要使用前面的技术,然后调用cache.delete_many(cache_keys)而不是cache.clear(),因为 Django Docs 警告说,使用 cache.clear() 将删除缓存中的所有键,而不仅仅是应用程序创建的键。

在我使用 Django 3.2 的设置中,有一种方法可以为 Redis 获取"原始"客户端,您可以从中获取密钥。

from django.core.cache import cache
cache.get_client(1).keys()
你可以

按照如何使用 Python memcached 检查 Django 缓存的内容中所述使用 http://www.darkcoding.net/software/memcached-list-all-keys/?

Memcached 文档建议不要列出所有缓存键,而是以详细模式运行 memcached 并查看所有更改的内容。你应该像这样启动内存缓存

memcached -vv

然后它将在创建/更新/删除密钥时打印密钥。

您可以使用以下

memcached_stats: https://github.com/dlrust/python-memcached-stats.这个包使得从python环境中查看memcached密钥成为可能。

如果这还不是太过时,我遇到了类似的问题,因为我不得不迭代整个缓存。当我向缓存中添加一些东西时,我管理了它,例如以下伪代码:

#create caches key list if not exists
if not my_cache.get("keys"):
    my_cache.set("keys", [])
#add to my cache
my_cache.set(key, value)
#add key to keys
if key not in my_cache.get("keys"):
    keys_list = my_cache.get("keys")
    keys_list.append(key)
    my_cache.set("keys", keys_list)

很有帮助。

裁判:

https://lzone.de/blog/How-to%20Dump%20Keys%20from%20Memcache

https://github.com/dlrust/python-memcached-stats

import re, telnetlib, sys
key_regex = re.compile(r"ITEM (.*) [(.*); (.*)]")
slab_regex = re.compile(r'STAT items:(.*):number')
class MemcachedStats:
    def __init__(self, host='localhost', port='11211'):
        self._host = host
        self._port = port
        self._client = None
    @property
    def client(self):
        if self._client is None:
            self._client = telnetlib.Telnet(self._host, self._port)
        return self._client
    def command(self, cmd):
        ' Write a command to telnet and return the response '
        self.client.write("{}n".format(cmd).encode())
        res = self.client.read_until('END'.encode()).decode()
        return res
    def slab_ids(self):
        ' Return a list of slab ids in use '
        slab_ids =  slab_regex.findall(self.command('stats items'))
        slab_ids = list(set(slab_ids))
        return slab_ids
    def get_keys_on_slab(self, slab_id, limit=1000000):
        cmd = "stats cachedump {} {}".format(slab_id, limit)
        cmd_output = self.command(cmd)
        matches = key_regex.findall(cmd_output)
        keys = set()
        for match_line in matches:
            keys.add(match_line[0])
        return keys
    def get_all_keys(self):
        slab_ids = self.slab_ids()
        all_keys = set()
        for slab_id in slab_ids:
            all_keys.update(self.get_keys_on_slab(slab_id))
        return list(all_keys)

def main():
    m = MemcachedStats()
    print(m.get_all_keys())
if __name__ == '__main__':
    main()

您可以按 LocMemCache 的相反顺序获取带有 cache._cache.keys() 的所有键。

例如,您设置 4 个缓存值,如下所示:

from django.core.cache import cache
cache.set("first_name", "John")
cache.set("last_name", "Smith", version=2)
cache.set("age", 36, version=3)
cache.set("gender", "Male")

然后,您可以按相反的顺序获取带有cache._cache.keys()的所有密钥,如下所示。 * 在每个键指示版本之前:1::2::3:

from django.core.cache import cache
print(cache._cache.keys())
# odict_keys([':1:gender', ':3:age', ':2:last_name', ':1:first_name'])

而且,您可以迭代所有键,如下所示:

from django.core.cache import cache
for key in cache._cache.keys():
    print(key)

输出:

:1:gender
:3:age
:2:last_name
:1:first_name

而且,您可以使用如下所示的版本迭代所有密钥:

from django.core.cache import cache
for key in cache._cache.keys():
    new_key = key.split(":", 2)[2]
    version = key.split(":", 2)[1]
    print(new_key, version)

输出:

gender 1
age 3
last_name 2
first_name 1

最后,您可以迭代与键和版本匹配的所有键值,如下所示。 *list(( 是cache._cache.keys()所必需的,否则你会得到错误,并且需要为 cache.delete(( 指定一个版本,否则你无法删除所有的缓存值,我的问题的答案用LocMemCache解释了缓存值的默认版本:

from django.core.cache import cache
        # `list()` is needed
for key in list(cache._cache.keys()):
    new_key = key.split(":", 2)[2]
    version = key.split(":", 2)[1]
    print(cache.get(new_key, version=version))

输出:

Male
36
Smith
John

你可以做一些奇怪的解决方法来从命令行获取所有密钥,但是没有办法在 Django 中使用 memcached 来做到这一点。请参阅此线程。

相关内容

  • 没有找到相关文章

最新更新