避免同一缓存区域的多次重新填充(由于并发性)
我有一个高流量的网站,我使用休眠。我还使用ehcache来缓存生成页面所需的一些实体和查询。
问题是“并行缓存未命中”,很长的解释是,当应用程序启动并且缓存区域是冷的时,每个缓存区域都会被不同的线程填充多次(而不是仅一次),因为站点同时被许多用户访问。此外,当某些缓存区域无效时,由于相同的原因,它将被多次重新填充。我该如何避免这种情况?
我设法通过将我自己的实现转换为BlockingCache,将1个实体和1个查询缓存转换为BlockingCache,hibernate.cache.provider_class但BlocktingCache的语义似乎不起作用。更糟糕的是,有时BlockblockCache会死锁(块),应用程序会完全挂起。线程转储显示处理在 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”的缓存之前,我用BlockblockCache对其进行修饰。“foo”是查询缓存,“bar”(相同的代码但省略)是pojo的实体缓存。
编辑2:“似乎不起作用”意味着最初的问题仍然存在。由于并发性,缓存“foo”仍然使用相同的数据多次重新填充。我通过用JMeter和10个线程强调网站来验证这一点。我希望9个线程阻塞,直到第一个从“foo”请求数据完成其工作(执行查询,将数据存储在缓存中),然后直接从缓存中获取数据。
编辑3:这个问题的另一种解释可以在 https://forum.hibernate.org/viewtopic.php?f=1&t=964391&start=0 上看到,但没有明确的答案。