什么是缓存?
缓存是介于应用程序和物理数据源之间,是为了降低应用程序对物理数据源的访问频率,从而提高应用程序的运行性能。
缓存的介质一般是内存,所以读写速度很快,如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质,缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期。
hibernante缓存包括session的缓存和sessionFactory的缓存,其中sessionFactory缓存分为两类:内置缓存和缓存。Session的缓存是内置的,不能被卸载,也被成为一级缓存。
SessionFactory的外置缓存是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件,外置缓存的数据是数据库的拷贝,外置缓存的介质可以是内存和硬盘,SessionFactory的外置缓存也被称为Hibernante的二级缓存。
SessionFactory的内置缓存和Session的缓存实现方式上比较相似,前者是SessionFactory对象的一些集合属性包含的数据,后指的是Session的一些集合属性包含的数据,SessionFactory的内置缓存中存放了映射元数据和预定义的SQL语句,映射元数据是映射文件中数据的拷贝,而预定义sql语句是在hibernate初始化阶段根据映射元数据推到出来的,SessionFactory的内置缓存只是只读的,应用程序不能修改缓存中的映射元数据和预定义sql语句,因此,sessionFactory不需要进行内置与映射文件的同步。
Hibernate的两级缓存都位于持久化层,存放的都是数据库数据的拷贝,那么他们有什么区别,为了理解二者的区别,需要审理理解持久化的缓存两个特性。
缓存范围和缓存并发访问策略。
持久化层的缓存范围决定了生命周期以及可以被谁访问。缓存的范围分为三类:事务范围、进程范围和集群范围。。
事务范围:缓存只能被当前事务访问。
进程范围:缓存被进程内的所有事务共享。
集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。慎用。
持久化层可以提供多种范围的缓存,如果在事务范围的缓存中没有查到相应的数据,还可以到进程范围内或者集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询。事务范围的缓存是持久化的第一级缓存,通常他是必需的,进程范围或者集群范围的缓存是持久化层的第二级缓存,他们是可选的。
持久化层的缓存的并发访问策略
当多个事务同时访问持久层的缓存数据时,会引起并发问题,必须采取必要的事务隔离措施。
在进程范围或者集群范围的缓存,即二级缓存,会出现并发问题,可以设置四中并发隔离策略,每一种策略对应一种事务隔离级别。
事务型:仅仅在受管理环境中适用。
它提供了Repeatable Read事务隔离级别,对于经常被读但很少修改的数据,可以采取这种隔离类型,因为他可以防止脏读和不可重复读这类的并发问题。
读写型:修改了Read Committed事务隔离级别。
仅仅在非集群的环境中适用。对于经常被读但很少修改的数据,可以采取这种隔离类型,可以防止脏读这类并发问题。
非严格读写型:不保证缓存与数据库中数据的一致性。
如果存在两个事务同时访问缓存中相同数据的可能,必须为该数据配置一个很短的数据过期时间,从而避免脏读;对于极少被修改,并且允许偶尔脏读的数据,可以采取这种并发访问策略。
只读型:
对于从来不会修改,如参考数据,可以使用这类并发访问策略。
二级缓存适合存放的数据:
1,很少被修改的数据
2,不是很重要的数据,允许出现偶尔并发的数据
3,不会被并发访问的数据
4,参考数据
二级缓存不适合存放的数据:
1,经常被修改的数据
2,财务数据,绝对不允许出现并发
3,与其他应用共享的数据。
如上所述:Hibernate两种缓存:
第一级Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此他的缓存是事务范围的缓存,第一级缓存是必须的,无法卸载。第一级缓存中,持久化类的每个实例都有唯一的OID。
第二级缓存是一个可插拔的缓存插件,他是由SessionFactory负责管理,由SessionFactory对象的生命周期和应用程序的整个过程对应。因此,二级缓存是进程范围或者集群范围的缓存。整个缓存中存放对象是松散数据。二级对象有可能出现并发问题,因此需要采取适当的并发访问策略,为被缓存的数据提供食物隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的,可以在每个类或者集合的力度上配置二级缓存。
Hibernate的二级缓存策略的一般过程如下:
1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。
2) 把获得的所有数据对象根据ID放入到第二级缓存中。
3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
4) 删除、更新、增加数据的时候,同时更新缓存。
Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query缓存。
Hibernate的Query缓存策略的过程如下:
1) Hibernate首先根据这些信息组成一个Query Key,Query Key包括条件查询的请求一般信息:SQL, SQL需要的参数,记录范围(起始位置rowStart,最大记录个数maxRows),等。
2) Hibernate根据这个Query Key到Query缓存中查找对应的结果列表。如果存在,那么返回这个结果列表;如果不存在,查询数据库,获取结果列表,把整个结果列表根据Query Key放入到Query缓存中。
3) Query Key中的SQL涉及到一些表名,如果这些表的任何数据发生修改、删除、增加等操作,这些相关的Query Key都要从缓存中清空。