我在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的两次执行。如您所见,它们在相同的GAE实例上仅相隔0.2秒运行。 &#34;缓存包含0-13&#34;是realCache中Map的关键。 &#34; realCache 29829270检索&#34;是我使用的Cache的哈希码。有两个,一个在我得到()缓存时记录,另一个在我put()时记录。您可以看到,在第二次执行中,&#34;缓存包含...&#34;在get()和put(),键#34; 1&#34;中有所不同不见了。这两次执行都运行正常,因为丢失的键&#34; 1&#34;不参与。但问题出现在后来的执行中&#34; code = 1&#34;先前累积的数据为&#34; 1&#34;不见了。您可以在下面的编码中看到我想要做的和我的问题。
以下是我的编码(为简单起见,跳过了日志记录代码):
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
请告知我的编码错误。
答案 0 :(得分:0)
你应该阅读有关appengine的各种文档。 JCache是一个标准的缓存api实现,它在appengine上使用了memcache。在appengine https://developers.google.com/appengine/docs/java/memcache/usingjcache上查看JCache文档的第一行。
appengine上的Memcache无法保证缓存中的条目存活。他们可以在任何时候被驱逐,而不是通知。请阅读关于appengine的memcache行为。
特别是google状态 - “通常,应用程序不应期望缓存值始终可用。” https://developers.google.com/appengine/docs/python/memcache/