Redis面试篇(1)

Redis缓存

一,缓存穿透

1.概述

查询数据,先在redis查找,找不到, 然后在DB中查找,找到,返回结果,并且返回之前先存到redis,就是每次请求会直接到数据库,而不会到redis。

2.解决方案

(1),缓存空数据,查询返回的数据为空,把这个结果仍然进行缓存,缺点是消耗内存
(2),使用布隆过滤器:主要作用是检索一个元素是否在一个集合中,,底层主要是先初始化一个比较大的数组,厘米那存放二进制的0,1,当进来的key经过3次hash计算,计算之后将数组改为1,3个1的数组位置就能确定key的存在,有缺点,就是会产生误判,但是很小,可以不计。

3.情景再现

HR:请聊一聊什么是缓存穿透,怎么解决?

你:缓存穿透是指查询一个一定不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。这种情况大概率是遭到了攻击。
解决方案的话,我们通常都会用布隆过滤器来解决它,布隆过滤器主要是用于检索一个元素是否在一个集合中。
它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一开始都是0,当一个kv来了之后经过3次hash计算,模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在。查找的过程也是一样的。
当然是有缺点的,布隆过滤器有可能会产生一定的误判,我们一般可以设置这个误判率,大概不会超过5%,其实这个误判是必然存在的,要不就得增加数组的长度,其实已经算是很划分了,5%以内的误判率一般的项目也能接受,不至于高并发下压倒数据库。

二,缓存击穿

1.概述

给key设置一个过期时间,key过期的时候,恰好这个时间点有大量的key并发请求数据库,会导致数据库在一瞬间奔溃,瘫痪。

2.解决方案

第一种方法:添加互斥锁,当key过期的时候,不立马去请求数据库,而是先用redis的setnx去设置一个互斥锁,特点是强一致性,性能差。
 第二种方法:逻辑过期,在设置key的时候,设置一个过期时间字段一块存入缓存,不给key设置过期时间,在查询的时候,从redis 中取出数据判断是否过期,若过期,则开通另一个线程进行数据同步。特点是高可用,性能优,但不保证数据的强一致性,

3.情景再现

HR:说一下什么是缓存击穿,怎么样解决?

你:缓存击穿的意思是对于设置了过期时间的key,缓存在某个时间点过期的时候,恰好这时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把 DB 压垮。

解决方案有两种方式:
第一可以使用互斥锁:当缓存失效时,不立即去load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db的操作并回设缓存,否则重试get缓存的方法
第二种方案可以设置当前key逻辑过期,大概是思路如下:
0):在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间

2:当查询的时候,从redis取出数据后判断时间是否过期
3):如果过期则开通另外一个线程进行数据同步,当前线程正常返回数据,这个数据不是最新当然两种方案各有利弊:
如果选择数据的强一致性,建议使用分布式锁的方案,性能上可能没那么高,锁需要等,也有可能产生死锁的问题
如果选择key的逻辑删除,则优先考虑的高可用性,性能比较高,但是数据同步这块做不到强一致。

三,缓存雪崩

1.概述

在同一段时间按内,大量的缓存key同时失效或者redis服务器宕机,导致大量请求到数据库,带来巨大的压力。

2.解决方案

利用redis集群提高的可用性,给不同的key在原有的失效时间增加一个1-5min的随机值,主要是降低过期时间的重复率,减少集体失效的时间。

3.情景再现

HR:说一下什么是缓存雪崩,怎么样解决呢?

你:

缓存雪崩意思是设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB 瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多key,击穿是某一个key缓存。解决方案主要是可以将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

四,缓存的双写一致性

1.概述

双写一致性:就是当修改了数据库的数据,也需要同时更新缓存的数据,要求保持一致

2.解决方案

解决办法:
     采用Redission的提供的读写锁:

1.共享锁,读锁readlock,加锁之后,其它的线程可以共享读操作
2.排他锁,独占锁writelock,阻塞其它线程的读写操作
       采用延迟双扇:先把缓存的数据删除,然后更新数据库,最后在延时删除缓存中的数据,但是不能保证强一致性,        而且可能在延时的这个过程中会产生脏数据。

3.情景再现

HR:redis做为缓存,mysql的数据如何与redis进行同步呢? (双写一致性)

你:

在读的时候添加共享锁,可以保证读读不互斥,读写互斥。当我们更新数据的时候,添加排他锁,它是读写,读读都互斥,这样就能保证在写数据的同时是不会让其要求性并没有那么高他线程读数据的,避免了脏数据。这里面需要注意的是读方法和写方法上需要使用同一把锁才行。

五,缓存的持久化

1.概述

缓存持久化是指将缓存中的数据持久化存储到磁盘或其他介质中,以防止数据在重启或意外宕机等情况下丢失。通常情况下,缓存系统中的数据都是存储在内存中的,而内存中的数据在断电或重启后会被清空,因此需要将数据持久化到硬盘上以保证数据的持久性。

2.解决法案

Redis 是一种内存数据库,通常用作缓存系统。在缓存持久化方面,Redis 提供了两种方式:RDB 持久化和 AOF 持久化。

  1. RDB 持久化:

    • RDB 持久化是通过快照的形式将数据集保存到硬盘上的文件中。可以手动执行 SAVE 或者 BGSAVE 命令,也可以根据配置文件中设定的条件自动触发持久化。
    • 优点:RDB 持久化适合大规模数据恢复,因为它只保存了生成快照时的数据状态,恢复速度比较快。
    • 缺点:如果 Redis 关闭时没有执行 SAVE 或 BGSAVE 命令,会导致数据丢失。
  2. AOF 持久化:

    • AOF 持久化是通过记录 Redis 服务器所执行的写命令来记录数据库状态的,当 Redis 重启时会重新执行这些写命令来恢复数据。
    • 优点:AOF 持久化对数据的持久化更加安全,因为它记录了每次写操作。
    • 缺点:相比于 RDB 持久化,AOF 持久化文件通常会比较大,而且重启时间可能比较长。

为了提高数据持久化的可靠性,通常可以将 RDB 持久化和 AOF 持久化结合起来使用,既保证了数据的及时持久化又保证了数据的安全性。

除了这两种主要的持久化方式外,Redis 还提供了混合持久化的方式,即在 AOF 持久化的基础上结合 RDB 持久化,同时利用两者的优势,提高数据的可靠性和恢复速度。

在配置 Redis 持久化时,需要根据具体的业务需求和数据安全性要求选择合适的持久化方式,并结合定期备份等措施来保障数据的完整性和可靠性。

六,数据过期策略

1.概述

问题相当于是当redis中的key到了过期时间,redis会立即删除吗?

2.解决方案

定期删除:对数据定期删除,假如说有key过期,就一定会删除他,

 惰性删除:对key设置过期时间之后,不去管它,需要时查看是否过期,是则删除,反之返回key   

七,数据的淘汰策略

1.概述

在redis中,redis作为缓存,它的容量是有限的,数据不可能只往里存,达到一定的值存满,此时就需要淘汰一些数据而接纳新的数据

2.解决方案

LRU算法:根据最近最少使用的key,用当前时间减去最后一次访问时间,值越大,淘汰的优先级越高。
LFU算法:根据最近的使用频率去淘汰。

3.情景再现

HR:Redis的数据淘汰策略有哪些?

你:嗯,这个在redis中提供了很多种,默认是noeviction,不删除任何数据,内部不足直接报错是可以在redis的配置文件中进行设置的,里面有两个非常重要的概念,一个是LRU,另外一个是LFULRU的意思就是最少最近使用,用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。LFU的意思是最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高
我们在项目设置的是allkeys-lru,挑选最近最少使用的数据淘汰,把一些经常访问的key留在redis中。

另外需要注意的是,redis内存被占满会发生报错,因为当内存满时,会停止任何的读写操作。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值