簡體   English   中英

獲取 Django 中的緩存鍵列表

[英]Get list of Cache Keys in Django

我試圖了解 Django 如何為我的視圖設置鍵。 我想知道是否有辦法從 Memcached 中獲取所有已保存的密鑰。 cache.all()類的東西。 我一直在嘗試使用cache.has_key('test')查找密鑰,但仍然無法弄清楚視圖密鑰的命名方式。

更新:我需要這個的原因是因為我需要手動刪除部分緩存但不知道鍵值 Django 正在為我的 cache_view 鍵設置

對於RedisCache,您可以獲得所有可用的鍵。

from django.core.cache import cache

cache.keys('*')

如前所述,無法獲取 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'

您可以從以下位置使用 memcached_stats: https : //github.com/dlrust/python-memcached-stats 這個包可以在 python 環境中查看 memcached 鍵。

切換到使用 LocMemCache 而不是 MemcachedCache:

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

然后看問題Contents of locmem cache in Django?

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

Memcached 文檔建議不要列出所有緩存鍵,而是在詳細模式下運行 memcached 並查看發生更改的所有內容。 你應該像這樣啟動 memcached

memcached -vv

然后它會在鍵被創建/更新/刪除時打印它們。

對於 Redis 后端

我要添加這個答案是因為我找到了這個 SO 問題來搜索完全相同的問題但使用不同的緩存后端。 同樣對於 REDIS,特別是如果您為多個應用程序使用相同的 REDIS 服務器,您將需要使用KEY_PREFIX選項 scope 緩存鍵,否則您最終可能會得到來自另一個應用程序的緩存鍵。

我的回答是,如果你在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 文檔警告使用cache.clear()將刪除緩存中的所有鍵,而不僅僅是應用創建的鍵。

如果這還不算過時,我也遇到過類似的問題,因為我不得不遍歷整個緩存。 我管理它,當我向我的緩存添加一些東西時,就像下面的偽代碼:

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

在我的設置中,有一種方法可以為 Redis 獲取“原始”客戶端,您可以從中獲取密鑰。

from django.core.cache import cache

cache.get_client(1).keys()

您可以采取一些奇怪的解決方法來從命令行獲取所有鍵,但是在 Django 中使用 memcached 無法做到這一點。 看到 這個線程

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM