Является ли Memcache (Java) для Google App Engine глобальным кешем? - PullRequest
15 голосов
/ 02 марта 2011

Я новичок в Google App Engine, и последние несколько дней я потратил на создание приложения с использованием Memcache GAE для хранения данных. Исходя из моих первоначальных результатов, кажется, что Memcache GAE НЕ глобален?

Позвольте мне объяснить подробнее. Мне известно, что разные запросы к GAE могут потенциально обслуживаться разными экземплярами (на самом деле это, кажется, происходит довольно часто). Именно по этой причине я использую Memcache для хранения общих данных, а не статической карты. Я подумал (возможно, неправильно), что это было смыслом использования распределенного кэша, чтобы к данным мог получить доступ любой узел.

Другая определенная возможность состоит в том, что я делаю что-то не так. Я пробовал и JCache, и низкоуровневый Memcache API (я пишу на Java, а не на Python). Вот что я делаю, чтобы получить кеш:

MemcacheService cache = MemcacheServiceFactory.getMemcacheService();

После развертывания я проверяю (через журналы приложений):

  1. Первоначальный запрос обслуживается конкретным узлом, а данные сохраняются в кеше, полученном выше.
  2. Несколько новых запросов извлекают этот же кеш, и данные там.
  3. Когда новый узел создается для обслуживания запроса (из журналов, которые я знаю, когда это происходит, потому что GAE регистрирует тот факт, что «Этот запрос вызвал запуск нового процесса для вашего приложения ...»), кэш извлекается и пуста !!

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

Надеюсь, кто-то сможет прояснить, как именно СЛЕДУЕТ вести себя. Если Memcache НЕ предполагается глобальным и каждый экземпляр сервера имеет свою собственную копию, то зачем вообще использовать Memcache? Я мог бы просто использовать статический HashMap (который я первоначально делал, пока не понял, что он не будет глобальным из-за различных случаев, обслуживающих мои запросы).

Помощь?

Ответы [ 3 ]

15 голосов
/ 02 марта 2011

Да, Memcache используется всеми экземплярами вашего приложения.

1 голос
/ 03 марта 2011

Я нашел проблему и заставил ее работать. Сначала я использовал API JCache и не смог заставить его работать, поэтому я переключился на низкоуровневый API Memcache, но забыл удалить старый код JCache. Таким образом, они две реализации наступали друг на друга.

Я не уверен, почему реализация JCache не сработала, поэтому я поделюсь кодом:

    try {
        if (CacheManager.getInstance().getCache(CACHE_GEO_CLIENTS) == null) {
            Cache cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
            cache.put(CACHE_GEO_CLIENTS, new HashMap<String, String>());
            CacheManager.getInstance().registerCache(CACHE_GEO_CLIENTS, cache);
        }

    } catch (CacheException e) {

        log.severe("Exception while creating cache: " + e);

    }

Этот блок кода находится внутри частного конструктора для синглтона с именем CacheService. Этот синглтон служит фасадом Cache. Обратите внимание, что поскольку запросы могут обслуживаться разными узлами, у каждого узла будет этот экземпляр Singleton. Поэтому, когда синглтон создается в первый и единственный раз, он проверит, доступен ли мой кэш. Если нет, он создаст его. Технически это должно произойти только один раз, так как Memcache является глобальным, да? Еще одна странная вещь, которую я здесь делаю, - это создание одной записи в кеш типа HashMap для хранения моих фактических значений. Я делаю это, потому что мне нужно перечислить все ключи, и это то, что я не могу сделать с Memcache изначально.

Что я здесь не так делаю?

0 голосов
/ 11 апреля 2012

Джерри, я вижу две проблемы с кодом, который вы разместили выше:

1) Вы используете версию API javax.cache.По словам Google, это устарело: http://groups.google.com/group/google-appengine-java/browse_thread/thread/5820852b63a7e673/9b47f475b81fb40e?pli=1

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

Я не знаючто использование старого API вызовет определенную проблему, но все же может быть проблемой.

2) Я не вижу, как вы помещаете и извлекаете из кэша, но выражение put у вас немного странно:

cache.put (CACHE_GEO_CLIENTS, new HashMap ());

Похоже, вы помещаете второй кеш в основной кеш.

У меня очень похожий код, но я помещаю и помещаю в кеш отдельные объекты, а не Карты, под ключом уникальный идентификатор.И он отлично работает для меня в нескольких случаях на GAE.

-Джон

...