hibernate的缓存

原文链接:https://my.oschina.net/bluesroot/blog/222581

缓存是数据库在内存中的临时容器,它包含了库表数据在内存中的临时拷贝,位于数据库和数据访问层中间。相对内存操作而言,数据库调用是一个代价高昂的过程,对于典型的企业级应用,数据库往往与应用服务器位于不同的物理服务器,这意味着每次数据访问都是一次远程调用,socket的创建于销毁,数据的打包拆包,数据库执行查询命令,网络传输上的必然延迟等等,这些消耗,方方面面的对我们系统的性能在进行影响。

 

此时,本地缓存的价值就尤为重要了,尤其是对于查询操作相对频繁的系统而言,如论坛系统,新闻系统等,良好的缓存机制以及合理的应用缓存,往往是提高性能的关键所在。

 

而在hibernate中,针对于可能发生的各种情况,它提供了一下三种缓存策略。1、事物级缓存  2、应用级/进程级缓存   3、分布式缓存

 

一、事物级缓存

这里的事物可以是数据库事物。也能是某个应用级事物。对于hibernate而言,事物级别缓存是基于session的生命周期实现的,每个session会在内部维持一个数据缓存,此缓存随着session的创建而存在,销毁而消亡,也称session缓存,一级缓存或者内部缓存。

 

二、应用级缓存

在某个应用或者某个独数据访问子集中的共享缓存。此缓存可以由多个事物(数据库事物或应用级事物)共享,事物之间的缓存共享策略与应用的事物隔离机制密切相关。在hibernate中,应用缓存在sessionfactory层实现,由它创建的session缓存实例共享此缓存,二级缓存,也叫sessionfactory级别缓存。在多实例并发运行时,我们必须特别小心此机制下,可能带来的负面效应,如实例a和b共享一个数据库,并行运行,a和b各自维护自己的缓存,如果缺乏同步机制,a对数据库做了更新,而b正在做读取,就会导致错误,这样的错误,对于关键业务是无法承受的,比如财务系统,银行系统等等。

在这种情况下,应用级缓存无法使用,为此,hibernate引入了分布式缓存。

 

三、分布式缓存

在多个应用实例中,多个jvm之间共享的缓存模式。分布式缓存由多个应用级缓存实例组成集群,通过某种远程机制(RMI或JMS)实现各个缓存实例间的数据同步,任何实例的数据修改操作,都将导致整个集群间的数据状态同步。

分布式缓存解决了多并发实例并发运行的数据同步问题,但是除非对于并发读取性能要求较高,且读取操作子啊持久层中占绝大部分比重的情况,分布式缓存的实际效果还需要进一步考证。

因为多实例间的同步,每个缓存实例发生变动都会复制到其余所有节点中,这个开销也是很大的。

 

四、一/二级缓存的应用

一级缓存常用于,1.通过id[主键]加载数据时   2.延时加载等等。由hibernate自动维护,无需手动干预,我们也可以通过调用session.evict[将某个特性对象从缓存中清除],和session.clear[清空内部缓存]。

 

二级缓存,是应用在一级中查不到的查不到的时候,才会在二级中去查找。在使用它时,我们必须考虑两点,第一,数据库是否于其他应用共享,第二,应用是否需要部署在集群中。假使出现第一种情况,那么我们不得不放弃二级的使用,假使出现第二种,则需要考虑清楚结合实际来使用。

那么当出现下面一些情况时,我们即可以使用二级缓存,1.数据不会被第三方应用修改   2.数据变动的大小在可接受范围内    3.数据更新频率较低    4.同一数据可能被系统频繁引用   5.非关键数据

 

五、第三方缓存实现

基于java缓存实现,最简单的方式莫过于对集合数据类型进行封装。hibernate提供了基于hashtable的缓存实现机制,不过由于性能和功能上的局限,一般用于调试使用。同时,hibernate还提供了面向第三方缓存实现的接口,如:

1.JCS   2.EHCache    3.OSCahce  4.JBoss Cache  5.SwarmCache,而新版本的hibernate中则将EHCache作为其默认的二级缓存实现。由此,在hibernate中开启二级缓存,需要在hibernate.cfg.xml中进行一下配置,代码如下:

Xml代码 
  1. <hibernate-configuration>  
  2. <session-factory>  
  3.    ........  
  4.    <property name="hibernate.cache.provider_class">  
  5.            net.sf.ehcache.hibernate.Provider  
  6.     </proerty>  
  7.    .........  
  8.   
  9. </session-factoty>  
  10. </hibernate-configuration>  

  另外还需对cache本身进行配置,这里是ehcache的配置文件,ehcache.xml:

Xml代码 
  1. <ehcache>  
  2.     <diskStore path="java.io.tmpdir">  
  3.      <defaultCache  
  4.             maxElementsInMemory="10000"   //允许最大保存对象的数量  
  5.             eternal="false"                               //是否为常量  
  6.             timeToIdleSeconds="120"            //缓存数据钝化时间  
  7.             timeToLiveSeconds="120"             //缓存数据的生存时间  
  8.             overflowToDisk="true"                   //内存不走是否启动磁盘缓存  
  9.       />  
  10. </ehcache>  

  之后,在我们的映射文件里,指定就行了:

Xml代码 
  1. <class name="com.entity.User"....>  
  2.      <cache usage="read-write"/>  
  3.       .....  
  4. <set name="address" .....>  
  5.       <cache usage="read-only"/>  
  6.       ..........  
  7. </set>  
  8.   
  9. </class>  

 

六、缓存同步策略

注意到上面我们对,<cache>节点的配置,hibernate提供了一下四种内置同步策略,

1.read-only:只读,对不会发生改变的数据,采用只读

2.nonstrict-read-write:并发访问下对同步要求不是和严格,且数据更新频率较低(几小时或几天)

3.read-write:严格可读写缓存,基于时间戳判定机制,虽不支持分布式缓存,但仍是应用中使用最多的同步策略

4.transactional:事物型缓存,必须运行在JTA事物环境中。

转载于:https://my.oschina.net/bluesroot/blog/222581

展开阅读全文
博主设置当前文章不允许评论。

没有更多推荐了,返回首页