获取 Django 中的缓存键列表

问题描述 投票:0回答:12

我试图了解 Django 如何为我的视图设置键。我想知道是否有办法从 Memcached 获取所有保存的密钥。类似

cache.all()
之类的东西。我一直在尝试使用
cache.has_key('test')
查找键,但仍然无法弄清楚视图键是如何命名的。

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

python django memcached django-cache django-caching
12个回答
36
投票

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

from django.core.cache import cache

cache.keys('*')

8
投票

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

但是如果你想知道如何将 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'

6
投票

为了调试,可以暂时切换到

LocMemCache
而不是
PyMemcacheCache

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

然后看这个问题

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

5
投票

对于Redis后端

我要添加这个答案,因为我遇到了这个SO问题,搜索完全相同的问题,但使用不同的缓存后端。另外,对于 REDIS,特别是如果您为多个应用程序使用相同的 REDIS 服务器,您将需要使用

KEY_PREFIX
选项来确定缓存键的范围,否则您最终可能会得到来自另一个应用程序的缓存键。

我的答案是如果您在

KEY_PREFIX
中设置了
settings.py
并且您正在使用
redis_cache.RedisCache
django.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("*")
还将返回属于 celery 任务的键

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 中的 ALL 键,您将需要使用先前的技术,然后调用

cache.delete_many(cache_keys)
而不是
cache.clear()
,因为 Django Docs 警告使用
cache.clear()
将删除缓存中的所有密钥,而不仅仅是您的应用程序创建的密钥。


4
投票

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

from django.core.cache import cache

cache.get_client(1).keys()


3
投票

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

memcached -vv

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


2
投票
您可以使用以下位置的 memcached_stats:

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


2
投票
如果这不是太过时,我也遇到过类似的问题,因为我必须迭代整个缓存。当我向缓存中添加一些内容时,我成功了,如以下伪代码所示:

#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)
    

0
投票
这有帮助。

参考:

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()
    

0
投票
您可以通过

cache._cache.keys()

 以相反的顺序获取 
LocMemCache 的所有密钥。

例如,您设置了 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()

的密钥,如下所示:

print(cache._cache.keys())
输出。 *每个键前的

:1:

:2:
:3:
表示
版本

odict_keys([':1:gender', ':3:age', ':2:last_name', ':1:first_name'])
并且,您可以迭代所有键,如下所示:

for key in cache._cache.keys(): print(key)
输出:

:1:gender :3:age :2:last_name :1:first_name
并且,您可以迭代所有没有 

Version 的键,如下所示:

for key in cache._cache.keys(): print(key.split(":", 2)[2])
输出:

gender age last_name first_name
    

-2
投票
您可以采取一些奇怪的解决方法来从命令行获取所有密钥,但无法使用 Django 内部的 memcached 来做到这一点。请参阅

此线程

© www.soinside.com 2019 - 2024. All rights reserved.