在Google App Engine中,不能在memcache
(作爲整體)存儲大於1 MB的對象。如何在GAE應用程序中緩存進程中常用的數據?
假設我想要緩存數據存儲查詢的結果,該數據存儲查詢包含1000條記錄(每個記錄5 KB) - 總共約5 MB。
如何進行?我可以將這些數據緩存在我的Web應用程序的Python進程中,而不是使用memcache
?例如,在一個全局變量?
請在下面找到我的答案。讓我知道你的想法。
在Google App Engine中,不能在memcache
(作爲整體)存儲大於1 MB的對象。如何在GAE應用程序中緩存進程中常用的數據?
假設我想要緩存數據存儲查詢的結果,該數據存儲查詢包含1000條記錄(每個記錄5 KB) - 總共約5 MB。
如何進行?我可以將這些數據緩存在我的Web應用程序的Python進程中,而不是使用memcache
?例如,在一個全局變量?
請在下面找到我的答案。讓我知道你的想法。
Google App Engine可能會解析針對不同進程甚至不同物理機器的不同Web請求。這意味着在不同請求之間維護全局狀態有點困難,也就是說,要實現本地緩存的數據。
當數據修改發生時,您必須小心地使本地緩存失效 - 在所有進程上(緩存一致性問題)。此外,如果您的GAE應用程序定義爲threadsafe
,則單個進程可以在不同線程中同時處理多個請求。
我勾畫了一個可能的解決方案:
memcache
記錄(當然只有版本標籤,而不是實際數據)value_provider
函數)下面是代碼:
import threading
from uuid import uuid4
from google.appengine.api import memcache
_data = dict()
_versions = dict()
lock = threading.Lock()
TIME = 60 * 10 # 10 minutes
def get(key, value_provider):
"""
Gets a value from the in-process storage (cache).
If the value is not available in the in-process storage
or it is invalid (stale), then it is fetched by calling the 'value provider'.
"""
# Fast check, read-only step (no critical section).
if _is_valid(key):
return _data[key]
# Data is stale (invalid). Perform read+write step (critical section).
with lock:
# Check again in case another thread just left the critical section
# and brought the in-process data to a valid state.
if _is_valid(key):
return _data[key]
version = memcache.get(key)
# If memcache entry is not initialized
if not version:
version = uuid4()
memcache.set(key, version, time=TIME)
_data[key] = value_provider()
_versions[key] = version
return _data[key]
def _is_valid(key):
"""Whether the in-process data has the latest version (according to memcache entry)."""
memcache_version = memcache.get(key)
proc_version = _versions.get(key, None)
return memcache_version and memcache_version == proc_version
def invalidate(key):
"""Invalidates the in-process cache for all processes."""
memcache.set(key, uuid4(), time=TIME)
參考文獻:
https://softwareengineering.stackexchange.com/a/222818
Understanding global object persistence in Python WSGI apps
Problem declaring global variable in python/GAE