`
xujunJ2EE
  • 浏览: 71074 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

hibernate的二级缓存不要轻易使用

阅读更多
一、hibernate的二级缓存
如果开启了二级缓存,hibernate在执行任何一次查询的之后,都会把得到的结果集放到缓存中,缓存结构可以看作是一个hash table,key是数据库记录的id,value是id对应的pojo对象。当用户根据id查询对象的时候(load、iterator方法),会首先 在缓存中查找,如果没有找到再发起数据库查询。但是如果使用hql发起查询(find, query方法)则不会利用二级缓存,而是直接从数据库获得数据,但是它会把得到的数据放到二级缓存备用。也就是说,基于hql的查询,对二级缓存是只写 不读的。

针对二级缓存的工作原理,采用iterator取代 list来提高二级缓存命中率的想法是不可行的。Iterator的工作方式是根据检索条件从数据库中选取所有目标数据的id,然后用这些id一个一个的 到二级缓存里面做检索,如果找到就直接加载,找不到就向数据库做查询。因此假如iterator检索100条数据的话,最好情况是100%全部命中,最坏 情况是0%命中,执行101条sql把所有数据选出来。而list虽然不利用缓存,但是它只会发起1条sql取得所有数据。在合理利用分页查询的情况下, list整体效率高于iterator。

二级缓存的失效机制由hibernate控制,当某条数据被修改之后,hibernate会根据它的id去做缓存失效操作。基于此机制,如果数据表不是被hibernate独占(比如同时使用jdbc或者ado等),那么二级缓存无法得到有效控制。

由于hibernate的缓存接口很灵活,cache provider可以方便的切换,因此支持cluster环境不是大问题,通过使用swarmcache、jboss cache等支持分布式的缓存方案,可以实现。但是问题在于:
1、 分布式缓存本身成本偏高(比如使用同步复制模式的jboss cache)
2、 分布式环境通常对事务控制有较高要求,而目前的开源缓存方案对事务缓存(transaction cache)支持得不够好。当jta事务发生会滚,缓存的最后更新结果很难预料。这一点会带来很大的部署成本,甚至得不偿失。

结论:XXXX不应把hibernate二级缓存作为优化的主要手段,一般情况下建议不要使用。

原因如下:
1、 XXXX 的DAO类大部分是从1.0升级过来,由于1.0采用的是hibernate 2.1,所以在批量删除数据的时候采用了native sql的方式。虽然XXXX2.0已经完全升级到hibernate 3.2,支持hibernate原生的批量删改,但是由于hibernate批量操作的性能不如sql,而且为了兼容1.0的dao类,所以很多地方保留 了sql操作。哪些数据表是单纯被hibernate独占无法统计,而且随着将来业务的发展可能会有很大变数。因此不宜采用二级缓存。
2、 针对系统业务来说,基于id检索的二级缓存命中率极为有限,hql被大量采用,二级缓存对性能的提升很有限。
3、 hibernate 3.0在做批量修改、批量更新的时候,是不会同步更新二级缓存的,该问题在hibernate 3.2中是否仍然存在尚不确定。

二、hibernate的查询缓存

查询缓存的实现机制与二级缓存基本一致,最大的差异在于放入缓存中的key是查询的语句,value是查询之后得到的结果集的id列表。表面看来这 样的方案似乎能解决hql利用缓存的问题,但是需要注意的是,构成key的是:hql生成的sql、sql的参数、排序、分页信息等。也就是说如果你的 hql有小小的差异,比如第一条hql取1-50条数据,第二条hql取20-60条数据,那么hibernate会认为这是两个完全不同的key,无法 重复利用缓存。因此利用率也不高。

另外一个需要注意的问题是,查询缓存和二级缓存是有关联关系的,他们不是完全独立的两套东西。假如一个查询条件hql_1,第一次被执行的时候,它 会从数据库取得数据,然后把查询条件作为 key,把返回数据的所有id列表作为value(请注意仅仅是id)放到查询缓存中,同时整个结果集放到class缓存(也就是二级缓存),key是 id,value是pojo对象。当你再次执行hql_1,它会从缓存中得到id列表,然后根据这些列表一个一个的到class缓存里面去找pojo对 象,如果找不到就向数据库发起查询。也就是说,如果二级缓存配置了超时时间(或者发呆时间),就有可能出现查询缓存命中了,获得了id列表,但是 class里面相应的pojo已经因为超时(或发呆)被失效,hibernate就会根据id清单,一个一个的去向数据库查询,有多少个id,就执行多少 个sql。该情况将导致性能下降严重。

查询缓存的失效机制也由 hibernate控制,数据进入缓存时会有一个timestamp,它和数据表的timestamp对应。当hibernate环境内发生save、 update等操作时,会更新被操作数据表的timestamp。用户在获取缓存的时候,一旦命中就会检查它的timestamp是否和数据表的 timestamp匹配,如果不,缓存会被失效。因此查询缓存的失效控制是以数据表为粒度的,只要数据表中任何一条记录发生一点修改,整个表相关的所有查 询缓存就都无效了。因此查询缓存的命中率可能会很低。

结论:XXXX不应把hibernate二级缓存作为优化的主要手段,一般情况下建议不要使用。

原因如下:
1、 XXXX的上层业务中检索条件都比较复杂,尤其是涉及多表操作的地方。很少出现重复执行一个排序、分页、参数一致的查询,因此命中率很难提高。
2、 查询缓存必须配合二级缓存一起使用,否则极易出现1+N的情况,否则性能不升反降
3、 使用查询缓存必须在执行查询之前显示调用Query.setCacheable(true)才能激活缓存,这势必会对已有的hibernate封装类带来问题。

总结
详细分析hibernate的二级缓存和查询缓存之后,针对XXXX项目的具体情况做出结论,在底层使用通用缓存方案的想法基本上是不可取的。比较好的做 法是在高层次中(业务逻辑层面),针对具体的业务逻辑状况手动使用数据缓存,不仅可以完全控制缓存的生命周期,还可以针对业务具体调整缓存方案提交命中 率。 Cluster中的缓存同步可以完全交给缓存本身的同步机制来完成。比如开源缓存swarmcache采用invalidate的机制,可以根据用户指定 的策略,在需要的时候向网络中的其他swarmcache节点发送失效消息,这一机制和XXXX1.0中已经采用的MappingCache的同步方案基 本一致
分享到:
评论

相关推荐

    hibernate二级缓存实例

    2. 配置Hibernate:在hibernate.cfg.xml文件中启用二级缓存,并指定使用Ehcache作为二级缓存提供者。 3. 配置实体类:在实体类上使用`@Cacheable`、`@Cache`等注解,声明该类及属性参与缓存。 4. 配置缓存策略:...

    hibernate一级缓存和二级缓存的区别与联系

    总结来说,Hibernate 的一级缓存和二级缓存都是为了提高数据访问效率,但它们在范围和并发控制方面有所不同。一级缓存是事务级别的,保证了数据的强一致性,而二级缓存提供了更多的灵活性,可以跨事务共享,但需要...

    Hibernate二级缓存

    1. **导入依赖**:首先,你需要添加ehcache库的jar包到项目的类路径中,因为Hibernate通常使用ehcache作为默认的二级缓存提供者。 2. **配置二级缓存**:在`hibernate.cfg.xml`配置文件中,需要指定二级缓存的提供...

    hibernate 二级缓存详解

    在Hibernate中,二级缓存可以使用不同的提供商,例如Ehcache和OSCache。配置Ehcache作为二级缓存提供商,需要在Hibernate的配置文件中设置`hibernate.cache.provider_class`为`...

    hibernate二级缓存示例源码

    综上所述,通过学习`hibernate二级缓存示例源码`,我们可以了解到如何在实际项目中配置和使用Hibernate二级缓存,从而提升系统的性能。在实际应用中,应结合具体场景选择合适的缓存策略,以达到最佳的性能优化效果。

    hibernate二级缓存包

    Hibernate二级缓存是Java开发中使用Hibernate框架进行数据持久化时优化性能的一种重要技术。它在一级缓存(Session级别的缓存)的基础上,提供了一个全局的、跨会话的数据存储层,可以显著减少对数据库的访问,从而...

    hibernate一级缓存、二级缓存和查询缓存

    **hibernate一级缓存、二级缓存和查询缓存** 在Java的持久化框架Hibernate中,缓存机制是提高应用程序性能的关键要素。缓存能够减少数据库的访问次数,提高数据读取速度,并且在一定程度上降低了系统的负载。本文将...

    day37 05-HIbernate二级缓存:一级缓存更新同步到二级缓存及二级缓存配置文件

    本篇文章将深入探讨Hibernate的二级缓存机制,以及如何进行一级缓存与二级缓存的同步,同时还会介绍二级缓存的配置文件设置。 一级缓存是Hibernate默认提供的缓存,每个SessionFactory实例都有一个一级缓存。当对象...

    Hibernate 二级缓存

    Hibernate 二级缓存

    Hibernate一级缓存和二级缓存

    Hibernate的一级缓存和二级缓存是提高数据访问效率的重要手段,它们各自承担着不同的角色,合理使用可以显著提升应用性能。然而,缓存的使用也需要谨慎,需要根据具体业务场景选择合适的缓存策略,并关注可能带来的...

    Hibernate 二级缓存 总结整理

    **Hibernate 二级缓存总结整理** 在Java的持久化框架中,Hibernate是一个广泛使用的ORM(对象关系映射)工具,它极大地简化了数据库操作。在处理大数据量或高并发的场景下,为了提高性能和减少数据库负载,...

    hibernate二级缓存java包下载

    二级缓存是 Hibernate 缓存策略的一部分,它在应用程序的多个会话之间共享数据,进一步优化了数据库访问效率。 二级缓存分为以下关键知识点: 1. **一级缓存与二级缓存的区别**: - 一级缓存:每个 Hibernate ...

    springboot+jpa(hibernate配置redis为二级缓存) springboot2.1.4

    通过以上步骤,我们就成功地在Spring Boot 2.1.4.RELEASE项目中配置了使用Redis作为Hibernate二级缓存的环境。这将显著提升数据库查询效率,减少对数据库的压力,尤其在高并发场景下,效果尤为明显。记得在实际生产...

    Spring集成的Hibernate配置二级缓存

    以EhCache为例,我们需要在项目中引入ehcache-core或ehcache的依赖,并在Hibernate配置文件(hibernate.cfg.xml或persistence.xml)中启用二级缓存,添加如下配置: ```xml <property name="hibernate.cache.use_...

    为Spring集成的Hibernate配置二级缓存

    5. **实体类注解**:为了让Hibernate知道哪些实体类需要使用二级缓存,可以在实体类上添加`@Cacheable`注解,并指定缓存区域。例如: ```java @Entity @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public...

    hibernate二级缓存所需要的 jar包

    5. 在代码中正常使用Hibernate,系统会自动处理二级缓存的读写。 总之,Hibernate的二级缓存机制对于提高系统的性能和响应速度具有显著效果。合理使用并配置好相关jar包,能有效优化数据访问,尤其在大数据量和高...

    hibernate 二级缓存

    本篇文章将深入探讨Hibernate二级缓存的概念、工作原理以及如何在实际项目中设置和使用。 **一、二级缓存概念** 一级缓存是每个Hibernate Session内部的一个内存区域,用于存储Session期间的操作对象。当Session...

    hibernate一级和二级缓存配置与详解

    本篇将深入探讨Hibernate的一级缓存和二级缓存,以及查询缓存的配置和使用。 ### 一级缓存 一级缓存是Hibernate默认提供的缓存,它是Session级别的,每个Hibernate Session都有一个私有的、本地的一级缓存。当我们...

    hibernate 二级缓存收集、总结、整理

    Hibernate作为一个成熟的ORM(对象关系映射)框架,它通过引入缓存机制极大地提高了数据...对于开发人员来说,理解Hibernate的二级缓存原理,并且能够合理配置和使用二级缓存,是构建高性能Java应用的关键技能之一。

Global site tag (gtag.js) - Google Analytics