开发者

Ehcache - using SelfPopulatingCache when data is not present

I am using the EhCache's decorator SelfPopulatingCache and have an issue when the cache tries to load a new entry, but it's non-existent (i.e. it doesn't exist in the database). So the cache will put a null value into the cache, to unblock any other gets on the key, but then the next thread will do the same database call because it received 'null' from the cache. which means it thinks the entry needs to be loaded - even though in rea开发者_JAVA百科lity it's null because the data doesn't exists anywhere. I feel like I'm doing something wrong.

(pseudo code)

Value v = cache.get(key); // multiple threads will block here
if (v == null)
   cache.put(key, getValueFromDB()); // this might put a null value

My current solution is to not put null, but to put a placeholder Object and check for it.

Value v = cache.get(key);
if (v == null)
   cache.put(key, getValueFromDB());
else if (v == NOENTRYOBJECT)
   return null;
else
   return v;

Thoughts?


We do something similar. In our case, we enter Boolean.FALSE into the cache if the requested key doesn't correspond to a valid item. It basically tells the calling code that the key that it asked for doesn't match any data. You need to make one call to the db on the first request for that key to discover that it doesn't correspond to valid data, but subsequent calls are spared the db lookup. Of course, if data is ever entered into the db for that key, you need to be sure to invalidate that cache entry (otherwise you'll be returning Boolean.FALSE even though there is actual data available).

Not sure if my response helps that much (it's not an alternative approach), but it at least validates that you're not alone in your approach.

BTW, I don't think this is unique to EHCache's SelfPopulatingCache.


The typical pattern is not to recheck the database if the item's KEY exists in the cache at all, rather than the VALUE.

The pattern is described in the ehcache docs here: Caching Empty Values.

Typically, but not always, get returns an Element, so get(id) won't be null if put(id, value) was ever previously called, even if value is null.

Note that this depends on the cache implementation. The ehcache documentation seems to suggest that it should always work, but BlockingCache (and its descendants) does NOT allow putting null values into the cache. The base ehcache Cache object does allow null values to be stored in the cache (as do many examples and custom implementations).

In all I think the solution you already have (placeholder value object), also works and should achieve the same result as the ehcache base Cache class and documentation.


I'm thinking you need to look into the CacheElementFactory. I had implemented this under spring for a project that I was working on to demand load information into the cache, if there was a cache miss an attempt was made to load it in from the database. I can't remember specifically what I did on this though and I think this would unfortunately result in a request being made to the database for every pass that requested the missing key.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜