当前位置: 首页 > 面试题库 >

EhCache休眠2级缓存maxBytesLocalHeap慢

万德海
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 ObjectGraphWalker必须调整放入缓存的实体的大小,因为我使用配置了单个缓存区域maxBytesLocalHeap

我的领域模型非常复杂,我知道可以通过@IgnoreSizeOf注释限制图表的移动,但是我不确定如何解决该问题:

  • 我是否必须忽略双向关联的一侧以避免循环?
  • 我是否必须显式忽略域模型类的临时成员?
  • 总的来说,maxBytesLocalHeap将EhCache与Hibernate一起使用是明智的选择还是我应该接受maxEntriesLocalHeap,因为Hibernate 仍在为每个实体保留一个单独的缓存区域?

[更新]:我发现,Hibernate不会缓存临时成员,所以无论如何ehcache都不应考虑它们。正确?


问题答案:

简短答案

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

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

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

更多细节

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

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

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


 类似资料:
  • 问题内容: 一级缓存与hibernate中的查询缓存是否不同?我看过有关第一级和查询缓存的文章,所以我很困惑。 问题答案: 默认情况下,第一级缓存处于启用状态,并且基于每个会话。默认情况下,查询缓存未启用,它在多个会话之间共享,应始终与二级缓存一起使用。 要启用查询缓存,应使用以下属性:

  • 问题内容: 在我的应用程序中,我使用了hibernate-core-4.1.8 jar,并希望将ehCache用作第二级缓存。我当前使用的jar是ehcache- core-2.5.0。我将其放置在WebContetn / WEB-INF / lib文件夹中,并将其放置在类路径中。 我的hibernate.cfg.xml看起来像这样: 放置在JavaResources / src文件夹中的ehca

  • 问题内容: 我正在使用Spring + JPA + Hibernate。我正在尝试启用Hibernate的二级缓存。在我的春天,我有: 运行时出现错误: 所以有人抱怨我没有启用二级缓存。我试图通过添加到我的启用它: 但是仍然没有喜悦。我还尝试将其添加到ehcache.xml中: 但这仍然行不通。将更改为也无济于事: 我的实体类被注释为使用缓存 那么,如何启用二级缓存? 编辑: 这是在bean下:

  • 问题内容: 我知道一个事实,它是 Hibernate 使用的一级缓存,一旦我们从中检索到一个实体,就会从而不是从DB中获取对具有 相同标识符 的 同一实体 的后续get调用,直到is Open 为止。 话虽如此,我对休眠如何将第一级缓存与数据库同步感到怀疑吗?考虑以下情形 所以我的问题是 由于是从一级缓存中提取的,因此有更新的值吗? 如果在会话打开时有人直接更新DB并修改User对象,那么是否与D

  • 问题内容: 我正在使用hibernate处理spring项目,并希望使用ehcache实现二级缓存。我看到了许多解决方法: 引入注释 一个旨在成为继任者的工具集。 可以很好地集成到休眠本身中,以使用例如注释进行缓存。 使用代理。基于注释的配置迅速变得有限或复杂(例如,注释嵌套的多个级别) 就我个人而言,我认为还不够彻底,因此我可能更愿意考虑发展得更为积极。尽管这似乎是最完整的实现(例如,读取和写入

  • 问题内容: 我该如何决定使用哪个? , , , 。 我阅读了https://www.hibernate.org/hib_docs/v3/api/org/hibernate/cache/CacheConcurrencyStrategy.html,但没有足够详细地解释。 问题答案: 在Hibernate文档确实在他们定义了很好的工作: 19.2.2。策略:只读 如果您的应用程序需要读取而不是修改持久类