+-
java-EhCache休眠第二级缓存maxBytesLocalHeap慢
在我的 Spring驱动的应用程序中,我使用Hibernate(4.2.15.Final)和EhCache(2.6.9)作为第二级缓存,在标准的持久层中进行了设置.

一切正常.但是,将条目放入第二级缓存有时会花费一些时间.

我已经在一个显式的ehcache.xml文件中配置了域模型类的缓存(我没有配置默认缓存):

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         name="hibernate"
         updateCheck="false" 
         monitoring="autodetect"
         dynamicConfig="false"
         maxBytesLocalHeap="300M"
         maxBytesLocalDisk="500M">

   <cache
    name="org.mycorp.model.MyEntity" 
    eternal="true"
    overflowToDisk="false"
    diskPersistent="false"
    maxBytesLocalHeap="5M" />

   ...

</ehcache>

在持久性上下文启动时,我收到以下INFO消息记录:

DefaultSizeOfEngine | using Agent sizeof engine

以及执行期间的以下警告

ObjectGraphWalker | The configured limit of 1,000 object references was reached while attempting to calculate the size of the object graph. Severe performance degradation could occur if the sizing operation continues. [...]

因为我用maxBytesLocalHeap配置了单个缓存区域,所以ObjectGraphWalker必须调整放入缓存的实体的大小.

我的域模型非常复杂,我知道可以使用@IgnoreSizeOf注释来限制图形的遍历,但是我不确定如何解决该问题:

>我是否必须忽略双向关联的一侧以避免循环?
>是否必须显式忽略域模型类的瞬态成员?
>通常,与EhCache一起与Hibernate一起使用时,与maxBytesLocalHeap一起使用是否明智?还是我应该为maxEntriesLocalHeap解决问题,因为Hibernate仍在为每个实体保留单独的缓存区域?

[更新]:我发现,临时成员将不会被Hibernate缓存(请参阅Hibernate: Is it possible to save a transient field in second level cache?),因此无论如何ehcache都不应考虑它们.正确?

最佳答案
简短答案

原来,我遇到的问题是由于在模型中使用了Joda-Time实例(我正在使用Jadira’s UserType library映射Joda类型).

Joda类型保留了各种内部引用(包括对导致年代久远的对象图的年代信息的引用),而Ehcache的SizeOfEngine遍历了这些引用,从而引起了我的原始警告.

我没有找到一种干净的方法来配置SizeOfEngine引擎以排除这些引用,但是我再次猜想,一种更干净的方法是强制Hibernate首先仅将相关信息放入第二级缓存(在我的时间实例中(LocalDateTimes).

更新资料

Jadira在实现其自定义类型时选择了一个糟糕的选择:请参见my answer here

更多细节

这是我关于OP的发现(使用Hibernate 4.2.15.Final,EhCache 2.6.9和UserType 3.2.0.GA):

首先,我对Hibernate如何在第二级缓存中存储实体存有误解.阅读Lorimer关于Truly Understanding the Second-Level and Query Caches的博客条目后,很多事情对我来说更有意义:

>您不必担心双向关联(或与此相关的循环图),因为Hibernate只会将关联的ID放入缓存中.即使将对整个实体的引用放入缓存中(但不是),EhCache的SizeOf Engine也会跟踪图中已访问过的对象,并且不会对它们进行两次大小调整.
>同样,您不必担心瞬态字段,因为Hibernate不会将它们放入缓存中
>从理论上讲,使用maxBytesLocalHeap配置应该没有任何问题.当前,当您使用EhCache的SizeOf引擎无法正确衡量的自定义用户类型时,会出现问题.

点击查看更多相关文章

转载注明原文:java-EhCache休眠第二级缓存maxBytesLocalHeap慢 - 乐贴网