获取 Django 中的缓存键列表

发布于 2024-12-29 07:18:25 字数 229 浏览 0 评论 0 原文

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

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

I'm trying to understand how Django is setting keys for my views. I'm wondering if there's a way to just get all the saved keys from Memcached. something like a cache.all() or something. I've been trying to find the key with cache.has_key('test') but still can't figure out how the view keys are being named.

UPDATE: The reason I need this is because I need to manually delete parts of the cache but dont know the key values Django is setting for my cache_view key

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

羅雙樹 2025-01-05 07:18:26
>>> from django.core.cache import cache
>>> cache.keys("foo_*")
["foo_1", "foo_2"]

像这样的简单搜索将返回所有匹配的值。在具有大量键的数据库中,这不是合适的方法。相反,您可以使用 iter_keys 函数,该函数的工作方式类似于 keys 函数,但使用 Redis 服务器端游标。调用 iter_keys 将返回一个生成器,然后您可以有效地迭代该生成器。

>>> from django.core.cache import cache
>>> cache.iter_keys("foo_*")
<generator object algo at 0x7ffa9c2713a8>
>>> next(cache.iter_keys("foo_*"))
"foo_1"

https://github.com/jazzband/django-redis #scan--批量删除密钥

>>> from django.core.cache import cache
>>> cache.keys("foo_*")
["foo_1", "foo_2"]

A simple search like this will return all matched values. In databases with a large number of keys this isn't suitable method. Instead, you can use the iter_keys function that works like the keys function but uses Redis server side cursors. Calling iter_keys will return a generator that you can then iterate over efficiently.

>>> from django.core.cache import cache
>>> cache.iter_keys("foo_*")
<generator object algo at 0x7ffa9c2713a8>
>>> next(cache.iter_keys("foo_*"))
"foo_1"

https://github.com/jazzband/django-redis#scan--delete-keys-in-bulk

回心转意 2025-01-05 07:18:26

这有帮助。

参考:

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

this helps.

Ref:

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()
似梦非梦 2025-01-05 07:18:26

您可以使用 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() 以相反的顺序获取所有键,如下所示。 * 每个键之前的 :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.keys() 否则你会得到错误并且需要为cache.delete() 否则你无法删除所有缓存值和答案 中的一个href="https://stackoverflow.com/questions/76936038/does-cache-set-use-version-1-by-default-instead-of-version-none-in-djang">我的问题使用 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

You can get all keys with cache._cache.keys() in reverse order for LocMemCache.

For example, you set 4 cache values as shown below:

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

Then, you can get all the keys with cache._cache.keys() in reverse order as shown below. *:1:, :2: or :3: before each key indicates version:

from django.core.cache import cache

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

And, you can iterate all the keys as shown below:

from django.core.cache import cache

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

Output:

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

And, you can iterate all the keys with the versions as shown below:

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)

Output:

gender 1
age 3
last_name 2
first_name 1

Lastly, you can iterate all the key's values which match the keys and versions as shown below. *list() is needed for cache._cache.keys() otherwise you get error and specifying a version is needed for cache.delete() otherwise you cannot delete all the cache values and the answer of my question explains the default version of a cache value with 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))

Output:

Male
36
Smith
John
等往事风中吹 2025-01-05 07:18:26

您可以使用一些奇怪的解决方法来从命令行获取所有密钥,但无法使用 Django 内部的 memcached 来执行此操作。请参阅此帖子

There are some weird workarounds you can do to get all keys from the command line, but there is no way to do this with memcached inside of Django. See this thread.

傲世九天 2025-01-05 07:18:25

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

from django.core.cache import cache

cache.keys('*')

For RedisCache you can get all available keys with.

from django.core.cache import cache

cache.keys('*')
阳光下的泡沫是彩色的 2025-01-05 07:18:25

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

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

https://docs.djangoproject.com/en/1.8/主题/缓存/#cache-key-transformation

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

As mentioned there is no way to get a list of all cache keys within django. If you're using an external cache (e.g. memcached, or database caching) you can inspect the external cache directly.

But if you want to know how to convert a django key to the one used in the backend system, django's make_key() function will do this.

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'
我们的影子 2025-01-05 07:18:25

对于 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("*") 还将返回属于 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 中的键,然后调用 cache.delete_many(cache_keys) 而不是 cache.clear() 作为 Django Docs 警告使用 cache.clear() 将删除缓存中的所有键,而不仅仅是应用程序创建的键。

For Redis Backend

I'm going to add this answer because I landed on this SO question searching for exactly the same question but using a different cache backend. Also with REDIS in particular if you are using the same REDIS server for multiple applications you will want to scope your cache keys with the KEY_PREFIX option otherwise you could end up with cache keys from another application.

My answer is for if you have setup KEY_PREFIX in your settings.py and if you are using either redis_cache.RedisCache or django.core.cache.backends.redis.RedisCache

e.g.

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

or

 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

Doing some tests shows that using Django's built in RedisCache may already be scoped but in my case I'm doing it to be explicit. calling .keys("*") will also return keys that belong to celery tasks

from django.conf import settings
from django.core.cache import cache

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

Bonus: Deleting all app keys

If you want to clear the cache for your specific app instead of ALL the keys in REDIS you'll want to using the prior technique and then call cache.delete_many(cache_keys) instead of cache.clear() as the Django Docs warns that using cache.clear() will remove ALL keys in your cache, not just the ones that are created by your app.

小傻瓜 2025-01-05 07:18:25

为了调试,您可以暂时切换到 LocMemCache< /code> 而不是 PyMemcacheCache

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

然后查看这个问题

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

For debugging, you can temporarily switch to LocMemCache instead of PyMemcacheCache:

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

then see this question:

from django.core.cache.backends import locmem
print(locmem._caches)
这个俗人 2025-01-05 07:18:25

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

from django.core.cache import cache

cache.get_client(1).keys()

In my setup with Django 3.2 there is a method to get a "raw" client for Redis which you can get the keys from.

from django.core.cache import cache

cache.get_client(1).keys()
野心澎湃 2025-01-05 07:18:25

Memcached 文档建议列出所有缓存键后,您可以在详细模式下运行 memcached 并查看所有发生更改的内容。您应该像这样启动 memcached

memcached -vv

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

The Memcached documentation recommends that instead of listing all the cache keys, you run memcached in verbose mode and see everything that gets changed. You should start memcached like this

memcached -vv

and then it will print the keys as they get created/updated/deleted.

や三分注定 2025-01-05 07:18:25

You can use memcached_stats from: https://github.com/dlrust/python-memcached-stats. This package makes it possible to view the memcached keys from within the python environment.

把时间冻结 2025-01-05 07:18:25

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

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

If this is not too out of date, I have had similar issue, due I have had to iterate over whole cache. I managed it, when I add something to my cache like in following pseudocode:

#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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文