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

问题描述:

我是Google App Engine的新手,最近几天我使用GAE的Memcache构建了一个应用程序来存储数据。根据我最初的研究结果,看起来GAE的Memcache不是全球性的?Google App Engine的Memcache(Java)是全局缓存吗?

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

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

MemcacheService cache = MemcacheServiceFactory.getMemcacheService(); 

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

  1. 初始请求是由一个特定节点提供服务,并将数据存储到上面检索的缓存中。
  2. 新的几个请求检索相同的缓存并且数据在那里。
  3. 当一个新节点被派生出来提供一个请求时(我知道这种情况发生的时间,因为GAE记录了“这个请求导致你的应用程序启动一个新进程”的事实),缓存被检索并且是空的!

现在我也知道不能保证数据在Memcache中的存储时间有多长,但从我的发现中可以看出,diff实例尝试访问缓存时数据已经消失。这似乎违背了分布式全局缓存的整个概念no?

希望有人能澄清这应该如何表现。如果Memcache不是全局的,并且每个服务器实例都有自己的副本,那么为什么要使用Memcache?我可以简单地使用静态HashMap(我最初做的直到我意识到它不会是全局的,因为不同的实例服务于我的请求)。

帮助?

+0

您能告诉我们从memcache中放入和检索值的代码吗? – 2011-03-02 19:41:07

+0

缓存被驱逐,并且您的应用在新实例上分散,似乎很可能是巧合 - 例如,两者都会在闲置一段时间后发生。 memcache和应用程序实例之间绝对没有直接联系。 – 2011-03-03 02:29:14

+0

我发现这个问题,并得到它的工作。我最初使用的是JCache API,无法使其工作,因此我切换到低级别的Memcache API,但忘记删除旧的JCache代码。所以他们的两个实现互相推进。 我不知道为什么JCache实施不起作用,所以我会分享代码。 – 2011-03-03 16:34:13

是的,Memcache在应用程序的所有实例*享。

我发现这个问题,并得到它的工作。我最初使用的是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单内。这个单身作为一个Cache门面。请注意,由于请求可以由不同节点提供服务,因此每个节点都将具有此Singleton实例。所以当Singleton被构建为第一次也是唯一一次时,它会检查我的缓存是否可用。如果没有,它会创建它。这从技术上讲应该只发生一次,因为Memcache是​​全球性的呀?我在这里做的另一个有点奇怪的事情是创建一个HashMap类型的单个缓存条目来存储我的实际值。我这样做是因为我需要枚举所有的密钥,这是我在本地无法使用Memcache执行的操作。

我在这里做错了什么?

杰里,有两个问题我和你上面贴的代码中看到:您正在使用的API的版本javax.cache

1)。根据Google的说法,这已被弃用: http://groups.google.com/group/google-appengine-java/browse_thread/thread/5820852b63a7e673/9b47f475b81fb40e?pli=1

取而代之的是,我们使用net.sf.jsr107库直到JSR完成。

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

2)我不知道你是如何把从缓存中获取,但你必须看跌语句是一个有点奇怪:

cache.put(CACHE_GEO_CLIENTS,新的HashMap());

它看起来像你正在主缓存中放置第二个缓存。

我有非常相似的代码,但我将个别对象放入缓存中,而不是使用唯一ID键入的地图。而且它在GAE上的多个实例中对我来说工作正常。

-John

+0

This 'CacheFactory cacheFactory = CacheManager.getInstance()。getCacheFactory(); cache cacheFactory.createCache(Collections.emptyMap()); cache.put(key,value);' 即使使用net.sf.watever也不适用于我! – 2013-02-16 08:35:46