首页 文章

EhCache Hibernate二级缓存maxBytesLocalHeap缓慢

提问于
浏览
3

我在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 注释来限制图形的行走,但我不确定如何解决这个问题:

  • 我是否必须忽略双向关联的一方以避免循环?

  • 我是否必须明确忽略我的域模型类的瞬态成员?

  • 一般来说,在将Hhnate与EhCache一起使用时使用 maxBytesLocalHeap 是否明智?或者我应该选择 maxEntriesLocalHeap ,因为Hibernate为每个实体保留了一个单独的缓存区域?

[UPDATE] :我发现,临时成员不会被Hibernate缓存(参见Hibernate: Is it possible to save a transient field in second level cache?),所以不管怎样他们都不应该被ehcache看待 . 正确?

2 回答

  • 1

    Short answer

    事实证明,我使用Jadira's UserType library来映射Joda类型的问题 .

    Joda类型保留了各种内部引用(包括对时间顺序信息的引用,从而产生巨大的对象图),Ehcache的 SizeOfEngine 将这些引用引导到我的原始警告 .

    我发现如何配置SizeOfEngine引擎以排除这些引用没有干净的方法,但是我想再一个更简洁的方法是强制Hibernate只将相关信息放到第二级缓存中(我的时间实例)案例 LocalDateTimes ) .

    Update

    Jadira在实现自定义类型时做出了糟糕的选择:参见my answer here

    More Details

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

    首先,我对Hibernate如何在其中存储实体产生了误解's 2nd-Level cache. After reading Lorimer'博客文章关于Truly Understanding the Second-Level and Query Caches很多事情对我来说更有意义:

    • 你没有't have to worry about bidirectional associations (or cyclic graphs for that matter), because Hibernate will only put IDs for your associations into the cache. And even if it would put a reference to the whole entity into the cache - which it doesn' t - EhCache的SizeOf引擎会跟踪已经访问过的图表中的对象,并且不会对它们进行两次调整 .

    • 同样,您不必担心瞬态字段,因为Hibernate不会将它们放入缓存中

    • 理论上, maxBytesLocalHeap 配置应该没有任何问题 . 当您使用EhCache的SizeOf引擎未正确测量的自定义用户类型时,会出现问题 .

  • 3

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

    最后我找到this page并解决它 .

相关问题