Hibernate缓存集成IMDG

1 第三方缓存插件

除了Ehcache这种轻量级的缓存方案外,几乎所有IMDG产品都提供了对Hibernate二级缓存的直接支持,常用的有:

?  Hazelcast

?  GridGain

?  JBoss Infinispan

?  Terracotta(额外提供了直接替换Session对象的集成方式)

2 缓存工作过程

下面以JVM集群Terracotta为例,首先从最原始的JDBC到Hibernate到开启Hibernate二级缓存,看一下应用对数据库请求的情况。

2.1 自动提交模式下的JDBC

在自动提交模式下使用JDBC时,JDBC不会对请求有任何缓存,每次SQL操作都会直接发送到数据库。因此下图中三个用户的访问会导致9次数据库访问。

2.2 Hibernate一级缓存

Hibernate有两级缓存(参考各种Hibernate进行复习),默认情况下第二级缓存是不开启的,后面会看到导致的问题。所以默认情况下,Hibernate会开启事务,并缓存更新操作,在最后事务提交时一起更新到数据库。算上commit事务提交的话,一共就是6次数据库访问。一级缓存在Session关闭时会自动清除,或者应用通过evict()清除某个对象、clear()清除全部缓存内容、flush()同步缓存与数据库。此外,与二级缓存相同的一点注意是:使用HQL或SQL查询属性级别的数据时,是不会使用缓存的。(第三部分缓存工作原理中会详细解释)

2.3 集成Hibernate二级缓存

Hibernate的二级缓存进一步将多个Session的数据加载请求缓存。然而风险也随之而来,当开启二级缓存后Hibernate不再每次都请求数据库,于是缓存中的数据可能是过期的。有时我们可以使用TTL设置来强制Hibernate刷新,但有的场景下这种方案也是不可行的。此时,就可以使用Terracotta将这些二级缓存形成集群,Terracotta负责集群结点间数据的同步。这种方式只需改动Hibernate配置文件即可,但由于Hibernate对二级缓存的使用方式的限制,这种集成方式并不能最大限度地发挥Terracotta的威力。

2.4 集成Hibernate Session

Terracotta与Hibernate最快的集成方式就是直接与Hibernate的Session对象集成。因为POJO对象在Hibernate的二级缓存中实际是以字节数组的形式保存的,因此尽管已经在缓存中了,但也有序列化的开销。而使用这种集成Hibernate Session的方式,应用代码可以零延迟地直接访问内存中的POJO对象,没有任何多余开销。同样,我们也能够零延迟地在内存中写POJO对象。此时,数据库成了系统的历史记录,只在需要时更新。

3 缓存内部工作原理

3.1 二级缓存

之所以叫二级缓存是因为当你打开session时,Hibernate会自动为你开启一个一级缓存。官方文档中对二级缓存是这样描述的:

A Hibernate Session is a transaction-level cache of persistent data. It is possible to configure a cluster or JVM-level (SessionFactory-level) cache on a class-by-class and collection-by-collection basis. You may even plug in a clustered cache. Be careful. Caches are never aware of changes made to the persistent store by another application (though they may be configured to regularly expire cached data).

像上面所提到的,只要SessionFactory开启着,二级缓存就存在。二级缓存持有每个标记为缓存的实体的所有属性关联。下面以Person实体为例,说明一下二级缓存的内部工作原理:

我们先不开启关联的缓存,来看一下基本属性的缓存。二级缓存中,Person对象的保存格式如下:key是id,value是firstName,middleInitial,lastName三个String,外加parent的id。所以很明显,对象的实例没有直接保存在缓存中,而是被拆分成一个个属性保存,Hibernate将这个过程称为对象脱水(dehydrate),反之属性组装成对象的过程称为补水(hydrate)。Hibernate为什么这样做?

?  用户代码对实体的实例上的修改不会破坏缓存,因为缓存里都是实例属性的拷贝。

?  对象间关联不容易过期,即使过期了也只是更新一个id就行了,因为缓存中不是直接保存parent变量对应的父Person实例,而只是其id。

不开启缓存和不开启关联缓存时,通过id加载操作对应的底层SQL执行情况如下。可以看出,如果不开启关联缓存的话,执行的SQL与不开启缓存时几乎一样(只省掉了查询父Person的第一条SQL):

现在开启关联缓存来看一下其效果。开启关联缓存后,Person的缓存格式如下。缓存内容多了子Person对象的id集合,与父Person缓存类似,也是只保存id而不是所有子Person实例。至此,Person对象本身以及嵌套的parent(Person)和children(Set<Person>)都被完全脱水成属性和关联id

此时,对Person对象的通过id加载操作完全不需要访问数据库了,所以一定要开启关联缓存才能真正发挥出二级缓存的效果。但是,当执行HQL或SQL查询时,依然不会使用二级缓存。例如,我们通过firstName进行HQL查询时,Hibernate会先执行一条具有相同where条件的SQL获取出Person的id,有了id之后才能开始使用二级缓存中的内容,也就是说:二级缓存只能在通过id查询时有用,对于其他复杂的条件查询是失效的。而这条查询出id的相同where条件的SQL就是查询缓存能发挥用处的地方,于是就引出了查询缓存。

3.2 查询缓存

首先要配置开启查询缓存

<property name="hibernate.cache.use_query_cache">true</property>

此外还要在使用Query对象前调用setCacheable(true)。

查询缓存也是key-value的形式,其key是HQL或SQL以及参数,而value是查询结果的id集合,所以其value与开启关联缓存后的二级缓存非常像。所以,只有在HQL或SQL一致,并且查询参数也完全一致的情况下,查询缓存才会有用!现在来看一下两种缓存共存时的效果。当二级缓存的关联缓存和查询缓存都开启时,当我们执行一个特定参数的HQL/SQL,首先会去查询缓存中找到对应的id,再去二级缓存中找到这些对象,以及这些对象关联的对象集合

3.3 总结

不论是二级缓存还是查询缓存,本质上都是key-value形式保存的,所以只能对key(id或HQL/SQL+参数)进行匹配查询。从这点上看,Hibernate缓存不够灵活,不能像IMDG产品那样,真正的将对象缓存在内存中,并提供面向对象的查询。理解了Hibernate缓存的底层工作原理,才能更好的管理我们的缓存数据,理解Hibernate缓存的行为。

参考资料

1 《The Definitive Guide to Terracotta》

Hibernate: Truly Understanding the Second-Level and Query Caches

时间: 2024-08-08 22:09:11

Hibernate缓存集成IMDG的相关文章

Hibernate 缓存机制

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的

Hibernate缓存管理

Hibernate缓存管理 ++YONG原创,转载请注明 1.    Cache简介: 缓存(Cache )是计算机领域非常通用的概念.它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能.缓存中的数据是数据存储源中数据的拷贝,应用程序在运行时直接读写缓存中的数据,只在某些特定时刻按照缓存中的数据来同步更新数据存储源. 缓存的物理介质通常是内存,而永久性数据存储源的物理介质通常是硬盘或磁盘,应用程序读写内在的

Hibernate 缓存机制详细解析

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的

Hibernate 缓存机制(转)

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的

[转]hibernate缓存机制所有详解

以下文章来自http://www.blogjava.net/tbwshc/articles/380013.html Hibernate 所有缓存机制详解 hibernate提供的一级缓存 hibernate是一个线程对应一个session,一个线程可以看成一个用户.也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了. hibernate一级缓存生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级缓存.如果tb事务提

hibernate缓存详解

为什么要用hibernate缓存? hibernate是一个持久层框架,经常访问物理数据库.为了降低应用程序对物理数据源访问的次数,从而提高应用程序的运行性能,我们想到使用hibernate缓存机制.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. hibernate缓存的原理 缓存的主要作用是查询. hibernate缓存包括三大类:hibernate一级缓存.hibernate二级缓存和hibernate查询缓存. 一

hibernate缓存机制(二级缓存)

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的

hibernate缓存机制【转】

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为"Session的

Hibernate缓存应用的积累与总结

Hibernate缓存一直比较难掌握,下面就分析和总结原因,相信你就会慢慢清楚了原来Hibernate缓存也是可以轻松掌握的,但前提要求大家必须跟着动手去验证一下,再用心体会,光看是没有用的 一.hibernate一级缓存(Session 级别的缓存) hibernate是一个线程对应一个session,一个线程可以看成一个用户.也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了.hibernate一级缓存生命周期很短,和session生命周期一样