当前位置: 首页 > 知识库问答 >
问题:

EhCache Hibernate 2nd level cache maxBytesLocalHeap slow

南宫泓
2023-03-14

我在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. [...]

AFAIK < code > ObjectGraphWalker 必须确定放入缓存的实体的大小,因为我用< code>maxBytesLocalHeap配置了单个缓存区域。

我的域模型相当复杂,我知道我可以使用@IgnoreSizeOf注释限制图的行走,但我不确定如何解决这个问题:

  • 我是否必须忽略双向关联的一侧以避免循环?
  • 是否必须显式忽略域模型类的瞬态成员?
  • 一般来说,在将EhCache与Hibernate一起使用时,使用maxBytesLocalHeap是明智的,还是应该满足于maxEntriesLocalHeap,因为Hibernate无论如何都为每个实体保留了一个单独的缓存区域?

[更新]:我发现,Hibernate不会缓存临时成员(请参阅Hibernate:是否可以在二级缓存中保存临时字段?),因此,ehcache无论如何都不应将其视为一种工具。对的

共有2个答案

戚阳
2023-03-14

我知道这是一个老问题。但它可能对某人有用。我也有同样的警告。我花了很多时间来解决这个问题。在我的例子中,EhCache不会忽略所有Hibernate代理类。我的实体有一些具有惰性关联的字段,并且在测量大小期间,EhCache遍历整个Hibernate图。

最后我找到了这个页面并解决了它。

裴令秋
2023-03-14

简短回答

事实证明,我遇到的问题是在我的模型中使用Joda-Time实例的结果(我使用Jadira的UserType库来映射Joda类型)。

Joda类型保存各种内部引用(包括对导致巨大对象图的时序信息的引用), Ehcache的< code>SizeOfEngine遍历这些引用,导致我最初的警告。

我发现没有干净的方法来配置SizeOfEngine引擎以排除这些引用,但我想更干净的方法是强制Hibernate首先将相关信息放入第2级缓存中(在我的情况下是时间实例LocalDateTimes)。

使现代化

Jadira在实现它的自定义类型时做了一个糟糕的选择:请看我的回答

更多详情

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

首先,我对Hibernate如何将实体存储在其2级缓存中有一个误解。在阅读了Lormer关于真正理解二级缓存和查询缓存的博客条目后,很多事情对我来说更有意义:

    < li >您不必担心双向关联(或循环图),因为Hibernate只会将关联的id放入缓存中。即使它会将对整个实体的引用放入缓存中——它不会这样做——EhCache的SizeOf引擎会跟踪已经访问过的图中的对象,不会调整它们的大小两次。 < li >同样,您不必担心瞬态字段,因为Hibernate不会将它们放入缓存中 < li >理论上,< code>maxBytesLocalHeap配置应该没有任何问题。目前,当您使用EhCache的SizeOf引擎无法正确测量的自定义用户类型时,会出现问题。
 类似资料:

相关问答

相关文章

相关阅读