hibernate二级缓存很慢

Posted

技术标签:

【中文标题】hibernate二级缓存很慢【英文标题】:hibernate second level cache is slow 【发布时间】:2016-05-10 23:45:00 【问题描述】:

我正在使用带有内存中 ehcache 的休眠二级缓存,它很慢。我的意思是,不比 SQL 慢,但考虑到 SSD 上的快速数据库,也不是真的快。实际速度提升不到 2 倍,有时甚至不明显。

似乎其他人也有同样的问题,但没有得到答案: http://forum.spring.io/forum/spring-projects/data/44353-hibernate-second-level-caching-slow-no-really-slow https://forum.hibernate.org/viewtopic.php?t=985913

经过一些分析后,似乎 hibernate 总是对缓存元素进行 de/re-hydration,而不是直接存储它们,这导致了这种糟糕的性能(与直接使用 ehcache 相比,超过 100 倍)。

所以,我的问题是:

hibernate 可以直接存储和恢复缓存的对象吗? 有没有其他方法可以加速二级缓存? 是否有相对简单的替代机制来加快休眠缓存?

【问题讨论】:

因为你问了三个问题而你应该只问一个问题,所以你立即将这个问题置于“太宽泛”的领域。 *** 是关于一次问一个问题,考虑将其拆分或缩小到您真正想知道的内容。这可能是为了放大 Hibernate 缓存性能问题。首先更具体地了解您使用的是哪个版本的 Hibernate。 嗯,问题的要点是“我想要更快的缓存”。如果这三个选项中的任何一个是可行的,我会很满意。 我认为这是跳跃点:“小于 2 倍”。在不知道您的应用程序在做什么的情况下,任何人如何解决这个问题?您能否整理出一个与您的应用程序类似的访问模式的示例或基准测试? 我也注意到了这一点。 L2C 与简单地在 SSD 上查询数据库的速度大致相同(在我的示例中为 28 毫秒与 33 毫秒)。 L2C 的第一次查询要慢得多!我预计 L2C 至少会快 2-3 倍,但我们拥有我们所拥有的。 【参考方案1】:

这是一个老问题,但其他人似乎对 Hibernate + Ehcache 有性能问题。我花了一段时间才找出问题所在,所以我在这里添加了我发现的内容,希望这可能对某人有所帮助。

JCache/JSR-107 规范规定,默认情况下缓存必须按值存储,而 Ehcache 默认为按引用存储。当使用 Ehcache 3 时,Hibernate 使用 jcache 接口,因此 Ehcache 通过使用序列化复制器来执行规范:在存储任何键或值之前,它们会在字节缓冲区中序列化。对于每个缓存 get() 和每个 put(),此操作需要相当多的 CPU 周期。

当默认复制器是IdentityCopier 时,Ehcache 切换到按引用存储(即基本上将对象直接放入缓存),请参阅CompleteConfiguration 的来源。

所以为了避免序列化/反序列化,我在我的 ehcache.xml 中添加了一个default-copiers 元素:

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ehcache.org/v3" xmlns:jsr107="http://www.ehcache.org/v3/jsr107">

    <service>
        <jsr107:defaults enable-management="false" enable-statistics="false" default-template="default" />
    </service>

    <default-copiers>
        <copier type="java.lang.Object">org.ehcache.impl.copy.IdentityCopier</copier>
    </default-copiers>
    
    <cache>...</cache>
    <cache-template name="default">...</cache-template>
</config>

【讨论】:

【参考方案2】:

您是否发现 Hibernate 二级缓存性能问题?在某些应用程序中,diskPersistence 和 overFlowToDisk 处于打开状态,并注意到 TRACE 日志中的克隆/序列化/反序列化。不明白为什么 Hibernate/Ehcache 必须再次克隆/反序列化本地 JVM 对象。

【讨论】:

不,我还没有弄清楚如何拥有快速的二级缓存。在关键的地方,我使用了一个带有分离对象的内存 ehcache。它确实有缺点,因为您必须小心不要尝试合并从该缓存中获取的对象。 只是想说我有完全相同的问题。用简单的 HashMap 替换 ehcache 3.8 的测试速度提高了大约 200 倍。反序列化真的那么慢吗? @kisna 看到我的回答,我可以通过设置 和使用 IdentityCopier 来提高缓存性能。但是,如果您正在执行磁盘操作,这可能不起作用(那么您显然需要序列化)。【参考方案3】:

hibernate可以直接存储和恢复缓存的对象吗?

不,它不能,因为这意味着并发会话将使用相同的对象实例,从而相互踩踏。

有没有其他方法可以加速二级缓存?

可能有数千种方法可以加快速度。其中大部分取决于您的应用程序的具体要求。

是否有相对简单的替代机制来加快速度 休眠缓存?

不,至少暂时不会。

【讨论】:

以上是关于hibernate二级缓存很慢的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate ——二级缓存

day37 07-Hibernate二级缓存:查询缓存

具体解释Hibernate中的二级缓存

hibernate 一级缓存和二级缓存

ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存

[原创]java WEB学习笔记93:Hibernate学习之路---Hibernate 缓存介绍,缓存级别,使用二级缓存的情况,二级缓存的架构集合缓存,二级缓存的并发策略,实现步骤,集合缓存,查询缓