数据缓存解决方案

前言

为什么要使用到缓存:主要还是由于数据库的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来说粉丝会有很多所以就会缓存最近的微博,防止粉丝在每一次的登录时候都需要从数据库中进行读取,对数据库的请求太大。还有就是对于四六级报名,也是先将报名信息缓存起来,等到凌晨时候再将数据读写到数据库。

发布了104 篇原创文章 · 获赞 92 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44015043/article/details/105746720
今日推荐