Django + memcached + 네임스페이스
소개
memcached 사용의 단점 중 하나는 와일드카드를 사용하여 키를 삭제할 수 없다는 것입니다. Django에서는 많은 키를 삭제할 수 있지만 삭제할 키 목록을 제공해야 합니다.
이 문제를 해결하는 방법은 네임스페이스를 사용하는 것입니다. 네임스페이스별로 키를 구성합니다. 예를 들어 판매하는 제품과 관련된 모든 키는 네임스페이스 제품에 속합니다. 그리고 클라이언트는 네임스페이스 클라이언트에 있습니다. 네임스페이스를 삭제하면 네임스페이스 내의 모든 키도 삭제됩니다. 불행하게도 우리는 memcached에서 네임스페이스를 지원하지 않는다는 또 다른 걸림돌에 부딪혔습니다.
이 문서에 제시된 코드를 사용하여 네임스페이스를 속이고 네임스페이스의 모든 키를 "삭제"할 수 있습니다.
TL;DR 코드를 확인하세요.
어떻게 해야 할까요?
memcached에 데이터를 저장할 때 키가 필요합니다. 우리가 할 일은 이 키 앞에 우리가 사용하려는 네임스페이스를 추가하는 것입니다. 키 기타의 경우 이 제품: 기타와 같은 키를 앞에 추가합니다.
기다리다! 네임스페이스 제품의 모든 키를 어떻게 무효화합니까? product를 접두사로 사용하는 대신 네임스페이스를 값과 함께 memcached에 저장합니다. 해당 값을 실제 네임스페이스로 사용합니다.
memcached의 네임스페이스 키는 namespace:product이며 값 1을 저장합니다. "하, 하지만 다른 네임스페이스와 충돌이 발생합니다"라고 말하는 것을 들었습니다. 귀하의 말이 맞으므로 이 product1과 같은 네임스페이스 자체를 이 값 앞에 추가하겠습니다. 이제 기타 키는 이 product1:guitar처럼 보일 것입니다.
product 값의 값을 product2로 변경하면 기타 키는 product2:guitar가 됩니다. 이제 네임스페이스 product1의 모든 키에 더 이상 연결할 수 없으며 memcached가 키를 제거합니다.
암호
Django 내에서 사용할 클래스에 이 모든 것을 래핑
# code/cache.py
import time
import xxhash
from django.core.cache import cache as django_cache
IS_DEVELOPMENT = False
CACHE_PREFIX = "MyApp"
HOUR = 3600
DAY = HOUR * 24
class MyCache:
"""
This class is used to create a cache for MyApp.
"""
def __init__(self, timeout=DAY):
"""
Initialize the cache.
"""
self.timeout = timeout if not IS_DEVELOPMENT else 20
def __str__(self):
"""
Return a string representation of the cache.
"""
return "MyCache"
def get(self, namespace, key):
"""
Get a value from the cache.
Parameters
----------
namespace: str
key: str
"""
try:
cache_key = self.safe_cache_key(namespace=namespace, key=key)
return django_cache.get(cache_key)
except Exception:
return None
def set(self, namespace, key, value, timeout=None):
"""
Set a value in the cache.
Parameters
----------
namespace: str
key: str
value: str|int|dict|list
timeout: int or None
"""
try:
cache_key = self.safe_cache_key(namespace=namespace, key=key)
timeout = timeout or self.timeout
django_cache.set(cache_key, value, timeout)
except Exception:
pass
def delete(self, namespace, key):
"""
Delete a value from the cache.
Parameters
----------
namespace: str
key: str
"""
try:
cache_key = self.safe_cache_key(namespace=namespace, key=key)
django_cache.delete(cache_key)
except Exception:
pass
def delete_namespace(self, namespace):
"""
Delete the namespace
Parameters
----------
namespace:str
"""
self.update_cache_namespace(namespace=namespace)
def safe_cache_key(self, namespace, key):
"""
Create a key that is safe to use in memcached
Parameters
----------
namespace: str
value: str
Returns
-------
str
"""
namespace = self.get_namespace(namespace=namespace)
new_key = "{}:{}:{}".format(
CACHE_PREFIX, namespace, xxhash.xxh3_64_hexdigest(key)
)
return new_key
def get_namespace(self, namespace):
"""
Get the namespace value for the given namespace
Parameters
----------
namespace: str
Returns
-------
str
"""
key = self.get_namespace_key(namespace=namespace)
rv = django_cache.get(key)
if rv is None:
value = self.get_namespace_value(namespace=namespace)
django_cache.add(key, value, DAY)
# Fetch the value again to avoid a race condition if another
# caller added a value between the first get() and the add()
# above.
return django_cache.get(key, value)
return rv
def update_cache_namespace(self, namespace):
"""
Update the value for the namespace key
Parameters
----------
namespace: str
"""
key = self.get_namespace_key(namespace=namespace)
value = self.get_namespace_value(namespace=namespace)
django_cache.set(key, value, DAY)
def get_namespace_key(self, namespace):
"""
Parameters
----------
namespace: str
Returns
-------
str
"""
return xxhash.xxh3_64_hexdigest(f"namespace:{namespace}")
def get_namespace_value(self, namespace):
"""
Create value for the namespace value
The namespace is used to make sure the hashed value is unique
Parameters
----------
namespace: str
Returns
-------
str
"""
namespace_value = namespace + str(int(round(time.time() * 1000)))
return xxhash.xxh3_64_hexdigest(namespace_value)
cache = MyCache()
용법
값 설정
cache.set("product", "combined_pricing", 5000)
가치를 얻으십시오
pricing = cache.get("product", "combined_pricing")
단일 키 삭제
pricing = cache.delete("product", "combined_pricing")
네임스페이스 삭제
cache.delete_namespace("product")
결론
이 코드를 사용하면 memcached 키를 그룹화하고 해당 네임스페이스의 키를 한 번에 모두 무효화할 수 있습니다.
메모
참조
오타를 찾았습니까?
이 블로그 게시물에서 오타, 개선할 수 있는 문장 또는 업데이트해야 할 사항을 발견한 경우 git 저장소를 통해 액세스하고 풀 요청을 할 수 있습니다. 댓글을 게시하는 대신 직접 이동하여 변경 사항이 포함된 새로운 풀 리퀘스트를 여세요.
Colin Lloyd의 사진 - https://unsplash.com/photos/62OEfKjU1Vs
Reference
이 문제에 관하여(Django + memcached + 네임스페이스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/petervanderdoes/django-memcached-namespace-4cde텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)