不了解Redis缓存,拿什么去征服面试官?

她剪了短发
好像温柔了许多
好像过的很好
好像也没那么好
其实我也不知道
我已经很久没有见过她了。

Redis缓存

  • Redis缓存
      • 为什么要使用Redis作为缓存,它为什么这么快?
      • SpringBoot中整合Redis作为Mybatis的二级缓存
      • Redis实现分布式集群环境Session共享
  • 缓存的收益和成本
      • 收益
      • 成本
  • 缓存可能会出现的问题
      • 缓存雪崩
      • 缓存穿透

无论是大厂小厂,在项目开发过程中,缓存肯定是离不开的,重要性也毋庸置疑。作为高频面试题,无论是为了应付面试,还是为了学到东西,都必须要认真对待。

Redis缓存

为什么要使用Redis作为缓存,它为什么这么快?

  1. 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)。
  2. 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的。
  3. 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。
  4. 使用多路I/O复用模型(多个网络连接复用一个线程,可以让单个线程高效的处理多个连接请求),非阻塞IO。
  5. 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

SpringBoot中整合Redis作为Mybatis的二级缓存

  • 引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
  • 开启缓存注解
//配置类添加注解
@EnableCaching
  • 具体操作类使用注解开启缓存使用
//一般作用在查方法上
//在执行方法前先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,执行该方法并将方法返回值放进缓存。
//参数: value缓存名、 key缓存键值、 condition满足缓存条件、unless否决缓存条件
@Cacheable
//一般作用于增加修改方法
//和 @Cacheable 类似,但会把方法的返回值放入缓存中
@CachePut
//一般作用于删除方法上
//方法执行成功后会从缓存中移除相应数据。
//value缓存名、 key缓存键值、 condition满足缓存条件、 unless否决缓存条件、 allEntries是否移除所有数据(设置为true时会移除所有缓存)
@CacheEvict

针对问题解决:

  1. 生成key过于简单,容易冲突------自定义KeyGenerator
  2. 无法设置过期时间,默认过期时间为永久不过期------自定义cacheManager,设置缓存过期时间
  3. 配置序列化方式,默认的是序列化JDKSerialazable------配置类自定义序列化方式

Redis实现分布式集群环境Session共享

在搭建完集群环境后,不得不考虑的一个问题就是用户访问产生的session如何处理。如果不做任何处理的话,用户将出现频繁登录的现象,比如集群中存在A、B两台服务器,用户在第一次访问网站时,Nginx通过其负载均衡机制将用户请求转发到A服务器,这时A服务器就会给用户创建一个Session。当用户第二次发送请求时,Nginx将其负载均衡到B服务器,而这时候B服务器并不存在Session,所以就会将用户踢到登录页面。这将大大降低用户体验度,导致用户的流失,这种情况是项目绝不应该出现的。

我们应当对产生的Session进行处理,通过粘性Session,Session复制或Session共享等方式保证用户的体验度。

使用Redis共享Session

  • 导入依赖
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
  • 配置类添加注解开启Session共享
//参数设置缓存时间
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 50)

redis保存的session格式为:

spring:session:sessions:expires:+‘sessionId’

缓存的收益和成本

收益

  1. 高速读写------缓存加速读写速度
  2. 降低后端负载------降低关系型数据库负载压力

成本

  1. 数据不一致------更新策略有问题将导致缓存数据和数据库数据不一致问题
  2. 代码维护成本------不仅要维护数据库,还要维护缓存
  3. 堆内缓存内存溢出------一般缓存方式分为堆内缓存和远程服务器缓存(redis),堆内缓存性能更高,不需要进行网络传输,远程缓存需要套接字传输。用户级别缓存建议远程缓存,大数据量建议远程缓存,服务节点化原则。

缓存可能会出现的问题

缓存雪崩

不了解Redis缓存,拿什么去征服面试官?_第1张图片

如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。

由于原有缓存失效,新缓存未到期间所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU 和内存造成巨大压力,严重的会造成数据库宕机。

◆解决

  1. 加锁排队------排斥锁
  2. 数据预热------可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的key。
  3. 双层缓存策略------C1为原始缓存,C2为拷贝缓存,C1失效时,可以访问C2,C1缓存失效时间设置为短期,C2设置为长期。
  4. 定时更新缓存策略------ 失效性要求不高的缓存,容器启动初始化加载,采用定时任务更新或移除缓存。
  5. 设置不同的过期时间------让缓存失效的时间点尽量均匀

详细说一下加锁排队

即第一个线程过来读取cache,发现没有,就去访问DB。后续线程再过来就需要等待第一个线程读取DB成功,cache里的value变得可用,后续线程返回新的value。

用到了加锁排队,吞吐率是不高的。仅适用于并发量不大的场景。

伪代码

public Object getCacheValue(String key, int expiredTime) {
    Object cacheValue = cache.get(key);
    if (cacheValue != null) {
        return cacheValue;
    } else {
        try {
            if (DistributeLock.lock(key)) {
                cacheValue = cache.get(key);
                if (cacheValue != null) { // double check
                    return cacheValue;
                } else {
                    cacheValue = GetValueFromDB(); // 读数据库
                    cache.set(key, cacheValue, expiredTime);
                }
            }
        } finally {
            DistributeLock.unlock(key);
        }
        return cacheValue;
    }
}

缓存穿透

缓存和数据库中都没有的数据,而用户不断发起请求,如果攻击者入侵,可能造成数据库压力大。

这里需要注意和缓存击穿的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

◆解决

  1. 缓存空对象------如果一个查询返回的数据为空,我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。 通过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库。
  2. 布隆过滤器------将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个bitmap 拦截掉,从而避免了对底层存储系统的查询压力(类似Set),为什么不用Set?因为布隆过滤器占用内存空间很小,bit存储。性能特别高。

文章持续更新,可以微信搜索「 绅堂Style 」第一时间阅读,回复【资料】有我准备的面试题笔记。
GitHub https://github.com/dtt11111/Nodes 有总结面试完整考点、资料以及我的系列文章。欢迎Star。
在这里插入图片描述

你可能感兴趣的:(JAVA,Redis,Spring,redis,缓存,分布式,java,spring,boot)