【学习笔记】缓存

缓存

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();
​
​
}

我们查询同一个数据

image-20230112110243165

可以发现,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的数据

    image-20230112111408862

    可以看到虽然修改的不是id为1的数据,但是第二次却执行了sql,说明没有从缓存中拿,缓存失效

 

  • 手动清理缓存

    用的是sqlSession的clearCache() 方法

    sqlSession.clearCache();

    image-20230112111717894

 

 

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,在查询该数据,在关闭

这时,这条数据,就是从一级缓存中放到二级缓存,然后从二级缓存中被取出来

image-20230112114311666

 

 

执行的顺序:二级缓存--->一级缓存--->数据库

 

posted @ 2023-01-12 12:06  GrowthRoad  阅读(43)  评论(0编辑  收藏  举报