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