0

GAE で JSR 107 JCache を使用して、Web から取得したデータを一時的に保存し、一定の間隔 (10 分) でデータストアに書き込みます。私のアプリは 1 つのキャッシュのみを使用します。ほとんどの場合、うまく機能します。ときどき (1 日あたり 4,000 回のうち 5 ~ 6 回)、不明な理由でキャッシュ内のエントリの 1 つが失われました。私は 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, 

これらは、私のサーブレットの 2 つの実行です。ご覧のとおり、それらはわずか 0.2 秒間隔で、同じ GAE インスタンスで実行されます。「Cache contains 0-13」は、realCache の Map のキーです。「realCache 29829270 Retrieved」は、私が使用するキャッシュのハッシュコードです。それらは 2 つあります。1 つはキャッシュを get() したときに記録され、もう 1 つは put() したときに記録されます。2 回目の実行では、"Cache contains ..." が get() と put() で異なり、キー "1" が欠落していることがわかります。不足しているキー「1」が関係していないため、これら 2 つの実行は正常に実行されました。しかし、"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