【问题标题】:Ehcache - using SelfPopulatingCache when data is not presentEhcache - 当数据不存在时使用 SelfPopulatingCache
【发布时间】:2010-12-29 04:31:14
【问题描述】:

我正在使用 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

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

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

想法?

【问题讨论】:

  • 我不清楚您的伪代码与SelfPopulatingCache 有何关系。你是怎么用的?
  • cache = SelfPopulatingCache (or BlockingCache) ... 认为这很清楚

标签: java ehcache


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    这里的 ehcache 文档中描述了该模式:Caching Empty Values

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

    请注意,这取决于缓存实现。 ehcache 文档似乎建议它应该始终有效,但BlockingCache(及其后代)does NOT allow putting null values into the cache。基础 ehcache Cache 对象确实允许将空值存储在缓存中(许多示例和自定义实现也是如此)。

    总的来说,我认为您已经拥有的解决方案(占位符值对象)也可以工作,并且应该达到与 ehcache 基础 Cache 类和文档相同的结果。

    【讨论】:

    • 实际上这不是真的 - 如果你查看 BlockingCache 和 put(..) 方法的代码 - 如果 value == null 它会从缓存中删除键。因此 put(id, null) 有效地将任何内容放入缓存中,下一次获取 id 将返回 null - 而不是 Element。
    • 嗯。我还没有看过代码,所以这将是最终的来源。但这似乎与 Ehcache 文档完全矛盾。如果您无法缓存空值(它明确告诉您这样做),我不确定“缓存空值”示例将如何工作。有机会时我会仔细查看代码,但我认为我记得过去曾这样做过并且效果很好(不确定介意你,模糊的回忆,我也会写确认/拒绝的简单测试)。
    • 我明白了。我的缓存实现没有使用任何内置的 Ehcache 实现,当然也没有使用 SelfPopulatingCache。我的 put 方法使用在名为 putNullInCache 的缓存实现上设置的布尔值。它默认为 true,因此允许 put 存储 null。所以它取决于缓存实现,你对 SelfPopulatingCache 是完全正确的。当我有机会时,我会更新我的“答案”以供任何人将来参考——但这确实是错误的;)。总而言之,我认为你正在做的事情无论如何都会产生相同的净效应。
    • 我已经更新了答案以反映我在这里学到的东西,仅供将来参考(这不是“正确”的答案,但我认为留下它比删除它更有意义,因为它试图澄清为什么这有时有效,而其他时候无效)。
    【解决方案3】:

    我认为您需要查看 CacheElementFactory。我在 spring 下为我正在处理的一个项目实现了这个,该项目要求将信息加载到缓存中,如果缓存未命中,则会尝试从数据库中加载它。虽然我不记得具体做了什么,但我认为这很遗憾会导致每次请求丢失密钥的过程都会向数据库发出请求。

    【讨论】:

      猜你喜欢
      • 2017-09-19
      • 1970-01-01
      • 2014-03-03
      • 2018-06-25
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多