2017-03-07 2 views
0

Google App Engineでは、memcacheに1 MBを超えるオブジェクトを(全体として)格納することはできません。GAEアプリケーションで頻繁に使用されるデータをインプロセスでキャッシュする方法はありますか?

データストアクエリの結果をキャッシュするとします。データストアクエリの結果は、それぞれ5KBの合計1000個のレコードで構成されます。合計で〜5 MBです。

どのように進めますか? memcacheの代わりに、このデータをWebアプリケーションのPythonプロセスでキャッシュすることはできますか?例えば、グローバル変数では?

私の答えは以下のとおりです。どう考えているか教えてください。

答えて

2

Google App Engineでは、異なるWeb要求を異なるプロセスや異なる物理マシンに解決することがあります。つまり、さまざまなリクエスト間でグローバル状態を維持すること、つまりローカルののデータを実装することは少し難しくなります。

データが変更された場合、すべてのプロセス(キャッシュ一貫性の問題)でローカルキャッシュを無効にするように注意する必要があります。

さらに、GAEアプリケーションがthreadsafeと定義されている場合、1つのプロセスで異なるスレッドで複数の要求を同時に処理できます。

私は可能な解決策をスケッチ:

  • を保つ
  • グローバル辞書を使用して、処理中のデータのバージョンを追跡するグローバル辞書
  • を使用してインプロセスデータを保持ゴールド小さなデータのバージョンmemcacheレコード(バージョンタグのみ、実際のデータではない)
  • インプロセスのローカルデータが無効(無効)の場合、から取り出します適切な場合は、ゴールドバージョンタグをリセットして、すべてのマシン間でインプロセスデータを無効にします。ここ

コードである:

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

関連する問題