2017-03-07 43 views
0

在Google App Engine中,不能在memcache(作爲整體)存儲大於1 MB的對象。如何在GAE應用程序中緩存進程中常用的數據?

假設我想要緩存數據存儲查詢的結果,該數據存儲查詢包含1000條記錄(每個記錄5 KB) - 總共約5 MB。

如何進行?我可以將這些數據緩存在我的Web應用程序的Python進程中,而不是使用memcache?例如,在一個全局變量?

請在下面找到我的答案。讓我知道你的想法。

回答

2

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

Python Threads - Critical Section

https://en.wikipedia.org/wiki/Cache_coherence

相關問題