Предел Memcache 1 МБ в Google App Engine

Как сохранить объект размером более 1 МБ в кэше памяти? Есть ли способ разделить его, но чтобы данные по-прежнему были доступны с одним и тем же ключом?


person Johnny    schedule 22.02.2011    source источник
comment
Какова природа объекта и почему вы пытаетесь кэшировать его в memcache?   -  person Nick Johnson    schedule 23.02.2011


Ответы (5)


Существуют методы кэширования памяти set_multi и get_multi, которые принимают в качестве аргументов словарь и префикс.

Если бы вы могли разделить свои данные на словарь фрагментов, вы могли бы использовать это. По сути, префикс станет вашим новым именем ключа.

Вам нужно будет как-то отслеживать имена чанков. Кроме того, ЛЮБОЙ фрагмент может быть удален из кэша памяти в любое время, поэтому вам также потребуется каким-то образом восстановить частичные данные.

person Calvin    schedule 22.02.2011

Я использую следующий модуль («кэш больших двоичных объектов») для хранения значений размером более 1 МБ в кэше памяти GAE.

import pickle
import random
from google.appengine.api import memcache


MEMCACHE_MAX_ITEM_SIZE = 900 * 1024


def delete(key):
  chunk_keys = memcache.get(key)
  if chunk_keys is None:
    return False
  chunk_keys.append(key)
  memcache.delete_multi(chunk_keys)
  return True


def set(key, value):
  pickled_value = pickle.dumps(value)

  # delete previous entity with the given key
  # in order to conserve available memcache space.
  delete(key)

  pickled_value_size = len(pickled_value)
  chunk_keys = []
  for pos in range(0, pickled_value_size, MEMCACHE_MAX_ITEM_SIZE):
    # TODO: use memcache.set_multi() for speedup, but don't forget
    # about batch operation size limit (32Mb currently).
    chunk = pickled_value[pos:pos + chunk_size]

    # the pos is used for reliable distinction between chunk keys.
    # the random suffix is used as a counter-measure for distinction
    # between different values, which can be simultaneously written
    # under the same key.
    chunk_key = '%s%d%d' % (key, pos, random.getrandbits(31))

    is_success = memcache.set(chunk_key, chunk)
    if not is_success:
      return False
    chunk_keys.append(chunk_key)
  return memcache.set(key, chunk_keys)


def get(key):
  chunk_keys = memcache.get(key)
  if chunk_keys is None:
    return None
  chunks = []
  for chunk_key in chunk_keys:
    # TODO: use memcache.get_multi() for speedup.
    # Don't forget about the batch operation size limit (currently 32Mb).
    chunk = memcache.get(chunk_key)
    if chunk is None:
      return None
    chunks.append(chunk)
  pickled_value = ''.join(chunks)
  try:
    return pickle.loads(pickled_value)
  except Exception:
    return None
person valyala    schedule 20.03.2011
comment
chunk_size не определен, вероятно, должен был быть MEMCACHE_MAX_ITEM_SIZE. В остальном выглядит как хороший код. Кажется, это работает для меня! - person phatmann; 23.07.2012
comment
Иногда значение chunk_keys выходило из кэша памяти в виде строки, а не списка. Итак, теперь, чтобы быть в безопасности, я использую объединение и разделение для преобразования его в строку и из строки. - person phatmann; 23.07.2012

Лучший способ сохранить большой блок данных в кэше памяти — разделить его на части и использовать set_multi и get_multi для эффективного хранения и извлечения данных.

Но имейте в виду, что некоторые части могут быть удалены из кеша, а другие останутся.

Вы также можете кэшировать данные в экземпляре приложения, сохранив их в глобальной переменной, но это менее идеальный вариант, поскольку они не будут использоваться совместно между экземплярами и с большей вероятностью исчезнут.

Поддержка загрузки в хранилище BLOB-объектов из приложения включена в дорожную карту GAE. возможно, вы захотите следить за этим, а также за интеграцией с Google Storage.

person Noah McIlraith    schedule 23.02.2011

Как уже упоминали другие ребята, вы можете добавить и получить сразу несколько значений из memcache. Интересно, что, хотя в блоге говорится эти массовые операции могут обрабатывать до 32 МБ, официальная документация. по-прежнему говорит, что они ограничены 1 МБ. Так что обязательно протестируйте его и, возможно, приставайте к Google с просьбой обновить их документацию. Также имейте в виду, что некоторые из ваших фрагментов могут быть удалены из кэша памяти раньше других.

Я бы рекомендовал погуглить python compress string и подумать о сериализации и сжатии вашего объекта перед его отправкой в ​​memcache.

Вы также можете спросить этого парня, что он имеет в виду расширение, которое позволяет ему хранить большие объекты в кэше памяти.

person dfichter    schedule 23.02.2011

Хороший обходной путь — использовать layer_cache.py, класс Python, написанный и используемый в Академии Хана (с открытым исходным кодом). По сути, это комбинация кеша в памяти (модуль кеша) с кешем памяти, который используется как способ синхронизации кеша в памяти через экземпляры. найдите здесь источник и прочитайте Бена Сообщение в блоге Каменса об этом здесь.

person orcaman    schedule 17.05.2014
comment
layer_cache.py, похоже, решает другую проблему, а именно ограничение на передачу данных из memcache (в ГБ/день). По крайней мере, это похоже на сообщение в блоге Бена Камена, на которое вы ссылаетесь. - person Tahir Akhtar; 30.04.2015