用于Google App Engine的Memcache(Java)是全局缓存吗?

时间:2011-03-02 16:02:28

标签: java google-app-engine caching memcached

我是Google App Engine的新用户,过去几天我使用GAE的Memcache构建应用程序来存储数据。根据我的初步调查结果,似乎GAE的Memcache不是全球性的?

让我进一步解释。我知道GAE的不同请求可能由不同的实例提供(实际上这似乎经常发生)。正是出于这个原因,我使用Memcache来存储一些共享数据,而不是静态Map。我想(也许是错误的)这是使用分布式缓存的重点,以便任何节点都可以访问数据。

另一个明确的可能性是我做错了什么。我已经尝试了JCache和低级Memcache API(我正在编写Java,而不是Python)。这就是我正在检索缓存的方法:

MemcacheService cache = MemcacheServiceFactory.getMemcacheService();

部署之后,这就是我检查的内容(通过我的应用程序日志):

  1. 初始请求由特定节点提供,数据存储在上面检索的缓存中。
  2. 新的少数请求检索此相同的缓存,数据就在那里。
  3. 当一个新节点被生成以提供请求时(从日志中我知道发生这种情况,因为GAE记录了“此请求导致为您的应用程序启动新进程的事实......”),检索到缓存并且是EMPTY !!
  4. 现在我也知道无法保证Memcache中的数据有多长,但从我的发现来看,当diff实例尝试访问缓存时,数据就会消失。这似乎违背了分布式全局缓存的整个概念吗?

    希望有人能够确切地说明这应该如何表现。如果Memcache不是全局的,并且每个服务器实例都有自己的副本,那么为什么甚至使用Memcache呢?我可以简单地使用静态HashMap(我最初做过,直到我意识到由于不同的实例为我的请求提供服务而不会是全局的。)

    帮助?

3 个答案:

答案 0 :(得分:15)

是的,Memcache在您的应用的所有实例中共享。

答案 1 :(得分:1)

我找到了问题并使其正常运行。我最初使用JCache API并且无法使其工作,因此我切换到低级Memcache API但忘记删除旧的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的单例的私有构造函数中。这个单例用作缓存外观。请注意,由于请求可以由不同的节点提供,因此每个节点都将具有此Singleton实例。因此,当第一次也是唯一一次构造Singleton时,它将检查我的缓存是否可用。如果没有,它将创建它。因为Memcache是​​全球性的,所以技术上应该只发生一次是啊?我在这里做的另一件奇怪的事情是创建一个HashMap类型的单个缓存条目来存储我的实际值。我这样做是因为我需要通过所有键进行枚举,这是我本地无法用Memcache做的事情。

我在这里做错了什么?

答案 2 :(得分:0)

杰瑞,我在上面发布的代码中看到了两个问题:

1)您正在使用API​​的javax.cache版本。根据Google的说法,这已被弃用: http://groups.google.com/group/google-appengine-java/browse_thread/thread/5820852b63a7e673/9b47f475b81fb40e?pli=1

相反,我们打算在完成JSR之前使用net.sf.jsr107库。

我不知道使用旧的API会导致特定的问题,但仍然可能会遇到麻烦。

2)我不知道你是如何放入缓存的,但是你所说的put语句有点奇怪:

  

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

看起来你在主缓存中放了第二个缓存。

我的代码非常相似,但我将单个对象放入缓存中,而不是使用唯一ID键入的地图。在GAE的多个实例中,它对我来说很好。

-John