Самодельный крошечный memcache - PullRequest
5 голосов
/ 23 октября 2010

Я перемещаю веб-приложение Google App Engine из «облака» в стандартную веб-среду ( webpy ), и мне хотелось бы узнать, как реализовать функцию memcache доступно в Gae.

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

Я наивно реализовал что-то вроде этого:

class TinyCache():
    class _Container():
        def __init__(self, value, seconds):
            self.value = value
            self.cache_age = datetime.now()
            self.cache_time = timedelta(seconds = seconds)
        def is_stale(self):
            return self.cache_age + self.cache_time < datetime.now() 

    def __init__(self):
        self.dict_cache={}

    def add(self, key, value, seconds = 7200):
        self.dict_cache[key] = self._Container(value, seconds)

    def get(self, key):
        if key in self.dict_cache:
            if self.dict_cache[key].is_stale():
                del self.dict_cache[key]
                return None
            else:
                return self.dict_cache[key].value
        else:
            return None

Типичное использование будет:

data = tinycache.get("remote_api_data")
if data is not None:
    return data
else:
    data = self.api_call()
    tinycache.add("remote_api_data", data, 7200)
    return data

Как я могу улучшить это?
Могу ли янужно сделать это Thread-Safe?

Ответы [ 2 ]

2 голосов
/ 29 октября 2010

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

Если вы хотите улучшить свой кеш, я бы добавил следующие две простые функции:

  1. Когда запрашивается Элемент, я бы перезапустил seconds к исходному значению.Поэтому, чтобы сохранить элементы, которые ваша система часто использует.
  2. Я бы реализовал в отдельном потоке механизм для обхода кэша и удаления слишком старых записей.

вы такжеможно получить некоторые идеи из этого Кеша фиксированного размера

Отредактировано

Я только что нашел этот рецепт, он очень крутой.По сути, вы можете обернуть с помощью декораторов функций ту логику, которую хотите кэшировать.Что-то вроде:

@lru_cache(maxsize=20)
def my_expensive_function(x, y):
    # my expensive logic here
    return result

Эти декораторы LRU и LFU будут реализовывать для вас логику кэширования.Наименее недавно использованные (LRU) или Наименее часто используемые (LFU) (см. Cache_algorithms для справки по ним)

0 голосов
/ 24 октября 2010

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

...

Как я могу улучшить это?

Если ваш код работает на вас, зачем?

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

Преимущества:

  • простой
  • нет проблем с несколькими процессами (например, FastCGI)
  • уменьшенный отпечаток памяти

Нужно ли сделать его потокобезопасным?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...