Ehcache - using SelfPopulatingCache when data is n

2019-04-28 12:05发布

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 reality 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?

标签: java ehcache
3条回答
男人必须洒脱
2楼-- · 2019-04-28 12:32

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.

查看更多
ら.Afraid
3楼-- · 2019-04-28 12:33

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.

查看更多
甜甜的少女心
4楼-- · 2019-04-28 12:38

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.

查看更多
登录 后发表回答