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

发布于 2024-10-20 02:58:08 字数 897 浏览 1 评论 0原文

我是 Google App Engine 的新手,最近几天我一直在使用 GAE 的 Memcache 来存储数据来构建一个应用程序。根据我的初步发现,GAE 的 Memcache 似乎不是全局的?

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

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

MemcacheService cache = MemcacheServiceFactory.getMemcacheService();

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

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

现在我还知道,无法保证数据会在 Memcache 中保存多久,但从我的发现来看,当 diff 实例尝试访问缓存时,数据似乎就消失了。这似乎违背了分布式全局缓存的整个概念不是吗?

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

帮助?

I'm new to Google App Engine, and I've spent the last few days building an app using GAE's Memcache to store data. Based on my initial findings, it appears as though GAE's Memcache is NOT global?

Let me explain further. I'm aware that different requests to GAE can potentially be served by different instances (in fact this appears to happen quite often). It is for this reason, that I'm using Memcache to store some shared data, as opposed to a static Map. I thought (perhaps incorrectly) that this was the point of using a distributed cache so that data could be accessed by any node.

Another definite possibility is that I'm doing something wrong. I've tried both JCache and the low-level Memcache API (I'm writing Java, not Python). This is what I'm doing to retrieve the cache:

MemcacheService cache = MemcacheServiceFactory.getMemcacheService();

After deployment, this is what I examine (via my application logs):

  1. The initial request is served by a particular node, and data is stored into the cache retrieved above.
  2. The new few requests retrieve this same cache and the data is there.
  3. When a new node gets spawned to serve a request (from the logs I know when this happens because GAE logs the fact that "This request caused a new process to be started for your application .."), the cache is retrieved and is EMPTY!!

Now I also know that there is no guarantee to how long data will be in Memcache, but from my findings it appears the data is gone the moment a diff instance tries to access the cache. This seems to go against the whole concept of a distributed global cache no?

Hopefully someone can clarify exactly how this SHOULD behave. If Memcache is NOT suppose to be global and every server instance has its own copy, then why even use Memcache? I could simply use a static HashMap (which I initially did until I realized it wouldn't be global due to different instances serving my requests).

Help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

知你几分 2024-10-27 02:58:08

是的,Memcache 在应用的所有实例之间共享。

Yes, Memcache is shared across all instances of your app.

猫卆 2024-10-27 02:58:08

我发现了问题并让它发挥作用。我最初使用的是 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 实例。因此,当第一次也是唯一一次构造单例时,它将检查我的缓存是否可用。如果没有,它将创建它。从技术上讲,这应该只发生一次,因为 Memcache 是全局的,是吗?我在这里做的另一件有点奇怪的事情是创建一个 HashMap 类型的单个缓存条目来存储我的实际值。我这样做是因为我需要枚举所有键,而这是 Memcache 本身无法做到的。

我在这里做错了什么?

I found the issue and got it working. I was initially using the JCache API and couldn't get it to work, so I switched over to the low-level Memcache API but forgot to remove the old JCache code. So they two implementations were stepping on each other.

I'm not sure why the JCache implementation didn't work so I'll share the code:

    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);

    }

This block of code is inside a private constructor for a singleton called CacheService. This singleton serves as a Cache facade. Note that since requests can be served by different nodes, each node will have this Singleton instance. So when the Singleton is constructed for the first and only time, it'll check to see if my cache is available. If not, it'll create it. This should technically happen only once since Memcache is global yeah? The other somewhat odd thing I'm doing here is creating a single cache entry of type HashMap to store my actual values. I'm doing this because I need to enumerate through all keys and that's something that I can't do with Memcache natively.

What am I doing wrong here?

晒暮凉 2024-10-27 02:58:08

Jerry,我发现您上面发布的代码存在两个问题:

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 上的多个实例中对我来说工作得很好。

-约翰

Jerry, there are two issues I see with the code you posted above:

1) You are using the javax.cache version of the API. According to Google, this has been deprecated:
http://groups.google.com/group/google-appengine-java/browse_thread/thread/5820852b63a7e673/9b47f475b81fb40e?pli=1

Instead, it is intended that we use the net.sf.jsr107 library until the JSR is finalized.

I don't know that using the old API will cause a specific issue, but still could be trouble.

2) I don't see how you are putting and getting from the cache, but the put statement you have is a bit strange:

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

It looks like you are putting a second cache inside the main cache.

I have very similar code, but I'm putting and getting individual objects into the cache, not Maps, keyed by a unique ID. And it is working fine for me across multiple instances on GAE.

-John

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文