【学习笔记】缓存
1.什么是缓存
缓存是存在内存中的临时数据。
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用去磁盘(关系型数据库数据文件)上查询,从缓存中查询,从而提高查询效率,解决高并发系统的性能问题。
为什么使用缓存?
-
减少和数据库的交互次数,减少系统开销,提高系统性能。
什么样的数据能使用缓存?
-
经常查询并且不经常改变的数据。
2.Mybatis缓存
Mybatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存,缓存可以极大地提升查询效率。
Mybatis系统中默认定义了两级缓存:一级缓存和二级缓存
-
默认情况下只有一级缓存开启(一级缓存也是sqlSession级别的,也成为本地缓存)
-
二级缓存需要手动开启和配置(二级缓存基于namespace的缓存)
-
为了提高扩展性,Mybatis定义了缓存接口Cache,我们可以通过实现这个接口来自定义缓存
3.一级缓存
一级缓存是默认开启的,存在区间是sqlSession的开启到关闭
使用场景:每次查询相同的数据,才会使用到一级缓存
举例:
public void test01(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
CityMapper mapper = sqlSession.getMapper(CityMapper.class);
City city = mapper.querycityById(1);
System.out.println(city);
System.out.println("================================");
City city1 = mapper.querycityById(1);
System.out.println(city1);
sqlSession.close();
}
我们查询同一个数据
可以发现,sql语句只执行了一次,也就是说,在这个sqlSession中,查询的数据被保存在缓存中,再去查询这条数据,就直接从缓存中取,不需要在查询数据库了。
关于一级缓存失效的情况:
-
查询不同的数据
-
通过不同的mapper.xml查询
-
增删改数据库的表,无论是不是你要查询的数据,缓存都会失效
public void test01(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); CityMapper mapper = sqlSession.getMapper(CityMapper.class); City city = mapper.querycityById(1); System.out.println(city); mapper.updateCity(new City(2,"德州",800)); System.out.println("================================"); City city1 = mapper.querycityById(1); System.out.println(city1); sqlSession.close(); }
我们先查询id为1的数据,然后修改id为2的数据,再去查询id为1的数据
可以看到虽然修改的不是id为1的数据,但是第二次却执行了sql,说明没有从缓存中拿,缓存失效
-
手动清理缓存
用的是sqlSession的clearCache() 方法
sqlSession.clearCache();
4.二级缓存
由于一级缓存的作用域只是在一个sqlSession中,作用域太小,所以需要二级缓存
二级缓存是基于namespace的缓存,作用域就是一个mappe.xml
工作机制:
-
一个会话(sqlSession)查询一条语句,这个数据就被保存在一级缓存中
-
当该会话关闭后,这个一级缓存就没了,一级缓存中的数据就被保存到二级缓存中
-
新的会话查询该数据,就直接从二级缓存中获取数据
-
不同的mapper查出的数据保存在自己的缓存中
二级缓存的使用:
在要使用缓存的mapper.xml中使用 标签 < cache /> 即可
还可以设置一些属性
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
可用的清除策略有:
-
LRU
– 最近最少使用:移除最长时间不被使用的对象。 -
FIFO
– 先进先出:按对象进入缓存的顺序来移除它们。 -
SOFT
– 软引用:基于垃圾回收器状态和软引用规则移除对象。 -
WEAK
– 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
举例:
public void test01(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
CityMapper mapper = sqlSession.getMapper(CityMapper.class);
City city = mapper.querycityById(1);
System.out.println(city);
sqlSession.close();
System.out.println("================================");
SqlSession sqlSession2 = SqlSessionUtils.getSqlSession();
CityMapper mapper2 = sqlSession2.getMapper(CityMapper.class);
City city1 = mapper2.querycityById(1);
System.out.println(city1);
sqlSession2.close();
}
我们先创建一个sqlSession,然后查询数据,再关闭sqlSession
然后在创建一个sqlSession,在查询该数据,在关闭
这时,这条数据,就是从一级缓存中放到二级缓存,然后从二级缓存中被取出来
执行的顺序:二级缓存--->一级缓存--->数据库