我有一个高流量的网站,我使用休眠。我还使用 ehcache 来缓存生成页面所需的一些实体和查询。
问题是“并行缓存未命中”,长的解释是,当应用程序启动并且缓存区域很冷时,每个缓存区域被不同的线程多次填充(而不是一次),因为该站点被许多用户访问同时。此外,当某些缓存区域失效时,由于相同的原因,它会被多次重新填充。我怎样才能避免这种情况?
通过向 hibernate.cache.provider_class 提供我自己的实现,我设法将 1 个实体和 1 个查询缓存转换为 BlockingCache,但 BlockingCache 的语义似乎不起作用。更糟糕的是,有时 BlockingCache 死锁(块)并且应用程序完全挂起。线程转储显示在执行 get 操作时 BlockingCache 的互斥体上的处理被阻塞。
那么,问题来了,Hibernate 支持这种使用方式吗?
如果没有,您如何在生产中解决这个问题?
编辑:hibernate.cache.provider_class指向我的自定义缓存提供程序,它是来自SingletonEhCacheProvider的复制粘贴,并且在 start() 方法的末尾(在第 136 行之后)我这样做:
Ehcache cache = manager.getEhcache("foo");
if (!(cache instanceof BlockingCache)) {
manager.replaceCacheWithDecoratedCache(cache, new BlockingCache(cache));
}
这样在初始化时,在其他人接触名为“foo”的缓存之前,我用 BlockingCache 装饰它。“foo”是查询缓存,“bar”(相同的代码但省略)是 pojo 的实体缓存。
编辑2:“似乎不起作用”意味着最初的问题仍然存在。由于并发性,缓存“foo”仍然被多次重新填充相同的数据。我通过使用具有 10 个线程的 JMeter 向站点施加压力来验证这一点。我希望这 9 个线程阻塞,直到第一个从“foo”请求数据以完成它的工作(执行查询,将数据存储在缓存中),然后直接从缓存中获取数据。
编辑 3:这个问题的另一种解释可以在https://forum.hibernate.org/viewtopic.php?f=1&t=964391&start=0但没有明确的答案。