0

我在 GAE 中使用 JSR 107 JCache 临时存储从 Web 捕获的数据,并以一定的时间间隔(10 分钟)将其写入数据存储区。我的应用程序只使用一个缓存。大多数时候它运作良好。偶尔(每天 4,000 次中有 5-6 次)缓存中的一个条目由于未知原因而丢失。我对 JCache 不是很熟悉,但我以某种方式理解我的应用程序可能在不同的 JVM 实例上运行,并且我的应用程序可能使用不同的 JCache 实例。

问题可以在下面的日志中找到:

2013-12-31 09:58:14.229 /cron/<myservlet>?code=11 200 ........... app_engine_release=1.8.8 instance=00c61b117c1599a88baa456ae838cbfa9b0f28
2013-12-31 09:58:14.011 <myapp>.RealCache validate: realCache 29829270 retrieved
2013-12-31 09:58:14.117 <myapp>.RealCache validate: Cache contains 0, 1, 2, 3, 4, 5, 6, 8, 11, 12, 13,
2013-12-31 09:58:14.121 <myapp>.RealCache get: Cache 11 has ...... <expected result>......
2013-12-31 09:58:14.121 cron.<myservlet> doGet: Appended with <mydata> for 11
2013-12-31 09:58:14.121 <myapp>.RealCache validate: realCache 29829270 retrieved
2013-12-31 09:58:14.224 <myapp>.RealCache validate: Cache contains 0, 1, 2, 3, 4, 5, 6, 8, 11, 12, 13, 

2013-12-31 09:58:14.443 /cron/<myservlet>?code=6 200 ............ app_engine_release=1.8.8 instance=00c61b117c1599a88baa456ae838cbfa9b0f28
2013-12-31 09:58:14.227 <myapp>.RealCache validate: realCache 29829270 retrieved
2013-12-31 09:58:14.326 <myapp>.RealCache validate: Cache contains 0, 1, 2, 3, 4, 5, 6, 8, 11, 12, 13, 
2013-12-31 09:58:14.329 <myapp>.RealCache get: Cache 6 has ..... <expected result>......
2013-12-31 09:58:14.329 cron.<myservlet> doGet: Appended with <mydata> for 6
2013-12-31 09:58:14.329 <myapp>.RealCache validate: realCache 29829270 retrieved
2013-12-31 09:58:14.437 <myapp>.RealCache validate: Cache contains 0, 2, 3, 4, 5, 6, 8, 11, 12, 13, 

这是我的 servlet 的 2 次执行。如您所见,它们仅在同一 GAE 实例上运行 0.2 秒。“Cache contains 0-13”是realCache中Map的key。“realCache 29829270 retrieved”是我使用的缓存的哈希码。其中有两个,一个在我 get() 缓存时记录,另一个在我 put() 时记录。可以看到,在第二次执行中,get() 和 put() 中的“Cache contains ...”不同,缺少键“1”。这两个执行运行正常,因为不涉及缺少的键“1”。但是,当“code=1”之前为“1”累积的数据丢失时,问题出现在以后的执行中。您可以在下面的编码中看到我想要做什么和我的问题。

这是我的编码(为简单起见跳过了记录代码):

public class RealCache {
    private static Cache realCache;
    public static synchronized void validate() {
        realCache = CacheManager.getInstance().getCache(Constants.Whale);
        if (realCache == null) {    //for first time of the day
             CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
             Map<String, Integer> props = new HashMap<>();
             props.put(GCacheFactory.EXPIRATION_DELTA, 28800);   //8 hrs is enough
             realCache = cacheFactory.createCache(Collections.emptyMap());  
             CacheManager.getInstance().registerCache(Constants.Whale, realCache);
         }
    }//end validate
    public static synchronized MyObj get(int code) {
        validate();
        MyObj myObj = (MyObj) realCache.get(code);
        return myObj;
    }//end get
    public static synchronized void put(int code, MyObj myObj) {
        validate();
        realCache.put(code, myObj);
    }//end put
}//end RealCache

这是我使用 RealCache 时的代码:

synchronized ("RealCache") {
    MyObj myObj = RealCache.get(code);
    if (myObj != null) {
        myObj.setData(myObj.getData() + newData);
        log.info("Appended with "+ newData+ " for "+ code);
    } else {
        myObj = new MyObj();
        myObj.setData(newData);
        log.warning("Created with "+ newData+ " for "+ code);
    }
    RealCache.put(code, myObj);
}//end sync

请告知我的编码有什么问题。

4

1 回答 1

0

您应该阅读 appengine 上的各种文档。JCache 是在 appengine 上使用 memcache 的标准缓存 api 实现。请参阅 appengine 上的 JCache 文档的第一行https://developers.google.com/appengine/docs/java/memcache/usingjcache

appengine 上的 Memcache 不保证缓存中的条目仍然存在。他们可以随时被驱逐,恕不另行通知。请阅读 appengine 上的内存缓存行为。

谷歌特别指出 - “一般来说,应用程序不应期望缓存值始终可用。” https://developers.google.com/appengine/docs/python/memcache/

于 2013-12-31T09:16:23.740 回答