文章目录
前言
为什么要使用到缓存:主要还是由于数据库的IO能力不足,因为对于很多的数据数量还是很大,存储在内存中会消耗很大的内存空间,而且对于很多的数据都需要持久化保存,所以大部分的数据需要存储在硬盘上,但是我们都知道对于硬盘的读写速度还是十分有限的,对于单节点的Mysql通常可以处理5000次的读取,和3000次的写入。
对于负载比较小的情况下,Mysql的响应时间通常可以在10ms以内完成,但是对于10000并发时候,要保证在10ms以内完成读写功能,对于任何的数据库都不能够做到。
所以这个时候就需要我们将数据一部分缓存在内存中,在读取的时候尽可能少去直接访问数据库,减少对于数据库的压力的同时也能够加快我们的访问的速度。
这里我们抛开前端浏览器的缓存,只考虑后台的缓存,可以分为数据库缓存,持久层缓存,业务层缓存等。下面我们来进行一一介绍。
数据库缓存
数据存在在内存中
我们可以将数据存在在内存中,这个时候对于请求来说,若是内存空间越大,对于缓存的命中就会越高,可以减少对于硬盘的访问,毕竟对于内存的访问速度来说就要比硬盘的读写要快得多,也就能加快访问的速度。
数据库业务数据分散存储
之间我们都是只用一块硬盘,对于一块硬盘的访问和IO读写能力都是有限的,这个时候我们使用到多块的硬盘,将数据的请求打在多块硬盘上面,多块硬盘的读写与IO能力较于一块还是有很大的提升。
搭建数据库集群
对于单节点的MySql,线程的数量还是有限的,也只能够支持有限的并发请求,对于高并发情况下,使用数据库集群也是数据库解决缓存的最终方案。
数据库缓存之查询缓存
对于开启了查询缓存情况下,数据库会把SELECT语句查询到的结果保存到缓存中,可以在Mysql的配置文件中进行以下的配置
query_cache_size=2048M # 缓存大小2G
query_cache_type=on # 开启缓存
这里我们需要注意的是对于MySql来说默认缓存是关闭的,但是我们想到不是说可以优化查询吗,为什么默认情况下却又是关闭的呢?
因为我们可能在一条
select * from student where classs like '2020%'
语句中查询学生表的所有情况,对于查询班级可能会有上百名学生,但是若是学生的,成绩进行了更改,那么此时这个缓存中的数据就会全部失效,这个时候也就增大了IO的负载,所以不建议开启查询缓存。
持久层缓存
对于Hibernate和MyBatis框架而言都有支持缓存的技术,具体分为一级缓存和二级缓存。
- 一级缓存是会话级别的缓存,Session关闭,缓存就会失效(查询缓存);
- 二级缓存就是引入第三方的存储机制缓存数据(是存储与框架之外)。
二级缓存
Mybatis支持多种的二级缓存技术,EHCache,Redis,Simple等等,同时对于Spring框架的Cache模块,可以管理MyBatis的二级缓存。下面我们来具体演示一下如何配置与使用二级缓存。
配置Redis二级缓存
在配置文件中加上对应配置信息
既然需要Sping框架的Cache支持,我们在配置文件中加上以下的配置
对于type字段表示缓存内型是什么这里是redis表示为redis类型。
cache-names: student
student 表示对于student模块开启缓存处理将来还要缓存什么数据,就在student后面加上逗号再加上具体的缓存对象。
同时在项目的启动类上添加如下注解:
具体使用 @Cacheable
在想要进行的查询上添加这个注解,在第一次请求数据时候,会请求到数据库,然后加入缓存中,在下一次请求相同数据时候就会直接走缓存,不会再走数据库查询。
@Override
// value 表示我们开启缓存的名字,key表示传入的参数。
@Cacheable(value = "student",key = "#id")
public StudentEntity getById(Serializable id) {
return super.getById(id);
}
但是我们需要思考的问题是,我们如何知道前端页面走到后端走的是数据库查询还是缓存查询,就需要我们对MyBatis进行一个配置,让查询sql语句打印到控制台。加上如下的配置信息。
测试
这个时候我们来进行一个测试,在第一次点击前端的查询以后
然后我们再度点击前端的查询页面,后台控制台发现并没有相同的查询语句表示了并没有走数据库,我们再度打开redis客户端进行查看(由于这里我没有安装redis客户端,截取老师图片进行演示)发现找到了对于studen的数据,当然是二进制保存。
后言
对于二级缓存的应用还是十分广泛的,若是大家想要进行测试,按照步骤来,自己定义对应的查询页面,加上注解和依赖,打开sql语句输出到控制台,就可以进行验证。
删除二级缓存数据
既然前面提交了可以在查询时候将数据添加到二级缓存中,那么要是数据被删除了对于缓存中的数据是否也应该被删除呢? 同样的方法来实现以下:
@CacheEvict(value = "student",key = "#id")
@Override
public boolean removeById(Serializable id) {
return super.removeById(id);
}
二级缓存的注解(@Cacheable)写在什么位置
在前面提到了将注解写在了Service层,于是就有思考为什么不写在controller
层或是Dao
层呢?
如下我们看一张图:
为什么不写在Dao上呢?因为对于一个sevice方法都知道可能会调用多个dao方法,然后将内容进行一个整理再放入到缓存中,在dao层就会显得杂乱不堪。
业务层缓存
对于业务层的缓存我们可以列举为购物车数据,头条新闻,秒杀商品的库存,公告通知等,例如对于微博大V来说粉丝会有很多所以就会缓存最近的微博,防止粉丝在每一次的登录时候都需要从数据库中进行读取,对数据库的请求太大。还有就是对于四六级报名,也是先将报名信息缓存起来,等到凌晨时候再将数据读写到数据库。