hiberante入门(十四):缓存2
程序员文章站
2022-04-17 08:10:16
...
>>步骤四、测试二级缓存:现在仍用前面的类来测试,尽管第一个session关闭了,但是我们在第二个session查询时,仍不会连库,这也就是二级缓存的作用,通常情况下,hibernate查询时会首先在一级缓存中查询数据,再到二级缓存中查询,如果仍查不到才会连库。 这时请注意,尽管我们在一级缓存中清掉了数据,但是在二级缓存中还存有数据,所以在清掉数据后执行的查询操作也不会引起连库,这就是为什么我们最终只看到一条查询语句的原因。强调,前面说用evict或clear只是清掉一级缓存中的内容。
>>步骤五、感知二级缓存:经过上面的测试我们不能明确感知到二级缓存的作用效果,下面我们配置“统计信息”属性来进行二级缓存信息的获取。首先我们在主配置文件中配置以下属性:<property name="hibernate.generate_statistics">true</property>来打开统计信息,由于统计信息会耗资源,所以一般不打开。然后在测试类的main方法中增加如下代码:
Statistics st = HibernateUtil.getSessionFactory().getStatistics();
System.out.println(st);
System.out.println("put:" + st.getSecondLevelCachePutCount());
System.out.println("hit:" + st.getSecondLevelCacheHitCount());
System.out.println("miss:" + st.getSecondLevelCacheMissCount());
执行后结果为:
put:1
hit:2
miss:1 在进行代码结果分析前先来说两个概念:命中,miss。命中是指在二级缓存中查到数据,没有找到就称为miss. 命中率:在查询时有多少次是从缓存中得到。 下面我们看上面的执行结果put=1,说明hibernate放了一次数据到缓存中,这发生在第一次查询时,当不能在二级缓存中找到(这也是为什么会有一次miss的原因)时,会去连库并把数据放到缓存中去,使put变为1.随后进行的三次查找中:第一次仍是从一级缓存中查找到,后两次查找均在二级缓存中查到,所以命中hit=2。
4.二级缓存中的细节问题:
(1)体会save自动填充缓存,save填充缓存不支持id的native方式生成,所以我们先修改User的实体配置文件让id生成方式为:
put:1
hit:3
miss:0 分析:当我们保存User对象到数据库时也会自动把此数据填充到缓存中,所以第一次put实质是发生在保存数据时。这样也就不难解释为什么hit=3,miss=0了。
(2)除了save外,update、saveOrUpdate、list、iterator、get、load(查询时从二级缓存中取数据的三个方法)、Query、Criteria都会填充二级缓存,且它们支持主键的nativa生成方式。
(3)让Query支持二级缓存:首先是主配置中配置如下属性:
<property name="#hibernate.cache.use_query_cache">true</property>因为Query命中率较低,所以默认此属性是关闭的。随后在Query方式查询时设置q.setCacheable(true);这两步执行后便完成了让Query支持二级缓存。
(4)怎样清除二级缓存:HibernateUtil.getSessionFactory().evict(User.class);这样将清除二级缓存中所有的User类相关的数据。
5.分步式缓存:
首先我们用图来模拟分步式缓存:
[img]http://dl.iteye.com/upload/picture/pic/47683/18ae1402-f66a-3257-ad9a-adc3e8e40cc1.gif[/img]说明:在大型的web系统中,通常都会采用多个服务器来进行web服务,比如在上面的实例中,我们在服务器一存有“数据data”,在服务器二中也存有这个数据,但当我们在服务器N中更改这个数据时,如果我们继续访问在服务器一或二的数据,将不能得到正确的数据,这时采取的方式就是只要有服务器改变这个数据就在这些服务器组成的内网中广播这个信息来更新每个改变的数据。虽然服务器在内网中通讯,但是这种方式也是非常耗资源的,后来提出了“*缓存”来解决此问题,如下图:
[img]http://dl.iteye.com/upload/picture/pic/47681/fcb20780-b589-341c-a555-85af86385b70.gif
[/img]
原理:当我们去某个服务器查询数据时,这个服务器会去*缓存查询,同样如果下面的某个服务器修改数据时,*缓存也会及时把数据更新到库并重新保存新数据。但是如果数据交互快的话,我们仍不能保证数据这些服务器访问*缓存时是及时数据。比如在服务器一访问*缓存修改数据时,其它的几个服务器也能访问修改,这样就不能保证及时获取正确信息。所以使用缓存的条件有如下几点:读取大于写入;数据量不能超过内存容量;对数据要有独立的控制;允许无效的数据存在。
>>步骤五、感知二级缓存:经过上面的测试我们不能明确感知到二级缓存的作用效果,下面我们配置“统计信息”属性来进行二级缓存信息的获取。首先我们在主配置文件中配置以下属性:<property name="hibernate.generate_statistics">true</property>来打开统计信息,由于统计信息会耗资源,所以一般不打开。然后在测试类的main方法中增加如下代码:
Statistics st = HibernateUtil.getSessionFactory().getStatistics();
System.out.println(st);
System.out.println("put:" + st.getSecondLevelCachePutCount());
System.out.println("hit:" + st.getSecondLevelCacheHitCount());
System.out.println("miss:" + st.getSecondLevelCacheMissCount());
执行后结果为:
put:1
hit:2
miss:1 在进行代码结果分析前先来说两个概念:命中,miss。命中是指在二级缓存中查到数据,没有找到就称为miss. 命中率:在查询时有多少次是从缓存中得到。 下面我们看上面的执行结果put=1,说明hibernate放了一次数据到缓存中,这发生在第一次查询时,当不能在二级缓存中找到(这也是为什么会有一次miss的原因)时,会去连库并把数据放到缓存中去,使put变为1.随后进行的三次查找中:第一次仍是从一级缓存中查找到,后两次查找均在二级缓存中查到,所以命中hit=2。
4.二级缓存中的细节问题:
(1)体会save自动填充缓存,save填充缓存不支持id的native方式生成,所以我们先修改User的实体配置文件让id生成方式为:
<id name="id">
<generator class="hilo"/>
</id>
后,这样修改后再来测试执行结果会发现执行结果为:put:1
hit:3
miss:0 分析:当我们保存User对象到数据库时也会自动把此数据填充到缓存中,所以第一次put实质是发生在保存数据时。这样也就不难解释为什么hit=3,miss=0了。
(2)除了save外,update、saveOrUpdate、list、iterator、get、load(查询时从二级缓存中取数据的三个方法)、Query、Criteria都会填充二级缓存,且它们支持主键的nativa生成方式。
(3)让Query支持二级缓存:首先是主配置中配置如下属性:
<property name="#hibernate.cache.use_query_cache">true</property>因为Query命中率较低,所以默认此属性是关闭的。随后在Query方式查询时设置q.setCacheable(true);这两步执行后便完成了让Query支持二级缓存。
(4)怎样清除二级缓存:HibernateUtil.getSessionFactory().evict(User.class);这样将清除二级缓存中所有的User类相关的数据。
5.分步式缓存:
首先我们用图来模拟分步式缓存:
[img]http://dl.iteye.com/upload/picture/pic/47683/18ae1402-f66a-3257-ad9a-adc3e8e40cc1.gif[/img]说明:在大型的web系统中,通常都会采用多个服务器来进行web服务,比如在上面的实例中,我们在服务器一存有“数据data”,在服务器二中也存有这个数据,但当我们在服务器N中更改这个数据时,如果我们继续访问在服务器一或二的数据,将不能得到正确的数据,这时采取的方式就是只要有服务器改变这个数据就在这些服务器组成的内网中广播这个信息来更新每个改变的数据。虽然服务器在内网中通讯,但是这种方式也是非常耗资源的,后来提出了“*缓存”来解决此问题,如下图:
[img]http://dl.iteye.com/upload/picture/pic/47681/fcb20780-b589-341c-a555-85af86385b70.gif
[/img]
原理:当我们去某个服务器查询数据时,这个服务器会去*缓存查询,同样如果下面的某个服务器修改数据时,*缓存也会及时把数据更新到库并重新保存新数据。但是如果数据交互快的话,我们仍不能保证数据这些服务器访问*缓存时是及时数据。比如在服务器一访问*缓存修改数据时,其它的几个服务器也能访问修改,这样就不能保证及时获取正确信息。所以使用缓存的条件有如下几点:读取大于写入;数据量不能超过内存容量;对数据要有独立的控制;允许无效的数据存在。