Ehcache – 在数据不存在时使用SelfPopulatingCache

我正在使用EhCache的装饰器SelfPopulatingCache并且当缓存尝试加载新条目时出现问题,但它不存在(即它在数据库中不存在)。 因此缓存会将一个null值放入缓存中,以取消阻止密钥上的任何其他获取,但随后下一个线程将执行相同的数据库调用,因为它从缓存中收到“null”。 这意味着它认为需要加载条目 – 即使实际上它是空的,因为数据不存在于任何地方。 我觉得我做错了什么。

(伪代码)

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

我目前的解决方案是不放置null,而是放置占位符Object并检查它。

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

思考?

我们做类似的事情。 在我们的例子中,如果请求的密钥与有效项不对应,我们将Boolean.FALSE输入到缓存中。 它基本上告诉调用代码它要求的密钥与任何数据都不匹配。 您需要在第一次请求该密钥时对数据库进行一次调用,以发现它与有效数据不对应,但后续调用不会进行数据库查找。 当然,如果数据曾经输入到该密钥的数据库中,则需要确保使该缓存条目无效(否则即使有可用的实际数据,您也将返回Boolean.FALSE)。

不确定我的回答是否有多大帮助(这不是一种替代方法),但它至少证实了你的方法并不孤单。

顺便说一句,我不认为这是EHCache的SelfPopulatingCache独有的。

如果项目的KEY完全存在于缓存中而不是VALUE ,则典型模式不是重新检查数据库。

此处的ehcache文档中描述了该模式: 缓存空值 。

通常,但并非总是如此, get返回一个Element ,因此如果先前调用了put(id, value)get(id)将不为null,即使value为null。

请注意,这取决于缓存实现。 ehcache文档似乎表明它应该始终有效,但BlockingCache (及其后代) 不允许将空值放入缓存中 。 基本ehcache Cache对象允许将空值存储在缓存中(许多示例和自定义实现也是如此)。

总而言之,我认为你已经拥有的解决方案(占位符值对象),也可以实现与ehcache基本Cache类和文档相同的结果。

我想你需要查看CacheElementFactory。 我在spring实现了这个项目,我正在努力将负载信息请求到缓存中,如果有缓存未命中,则尝试从数据库加载它。 我不记得具体是我在这方面做了什么,我认为不幸的是,这会导致向数据库请求丢失密钥的每个传递请求。