1.什么是缓存穿透?怎么解决?
缓存穿透是指查询一个不存在的数值,先访问redis,redis缓存中不存在无法命中,就会访问数据库。如果高并发的访问这样的接口,会给数据库造成巨大的压力。
解决方法:在我们项目中会使用布隆过滤器来缓存穿透的问题,单缓存命中时基于布隆过滤器来判断数据是否存在,不存在就拒绝。
我们也可以使用缓存空值的方式来讲解,不过这种方案比较浪费内存。
2.能介绍一下布隆过滤器嘛?
布隆过滤器主要是用于检索一个元素是否存在一个集合中。我们当时使用的是redisson实现布隆过滤器。
他的底层主要是先初始化一个比较大的数组,里面存放的二进制的0和1。在一开始的时候都是0,当一个key来了后,经过3次的hash计算,模于数组的长度找到下标把0变成1。但是也是存在误判的概率的。
3.什么是缓存击穿?怎么解决?
缓存击穿往往是由于热点的Key引起的,当热点的key过期时,大量请求涌入同时查询,发现缓存未命中,去访问数据库,导致数据库的压力增大。
解决方法:思路:避免多线程并发去重建缓存。
(1)互斥锁。当发现缓存未命中时,需要加入互斥锁,重建缓存,缓存重建后释放锁。主要可以包中缓存在同一时间内只会有一个线程执行。 这样可能导致性能下降严重。
(2)逻辑过期,也就是不给热点Key设置过期时间,而是给数据添加一个过期时间的字段。这样热点Key就不会过期,缓存中永远有数据。
查询到数据时基于其中的过期时间判断key是否过期,如果过期开启独立新线程异步的重建缓存,而查询请求先返回旧数据即可。当然,这个过程也要加互斥锁,但由于重建缓存是异步的,而且获取锁失败也无需等待,而是返回旧数据,这样性能几乎不受影响。
需要注意的是,无论是采用哪种方式,在获取互斥锁后一定要再次判断缓存是否命中,做dubbo check. 因为当你获取锁成功时,可能是在你之前有其它线程已经重建缓存了。
- 什么是缓存雪崩 ? 怎么解决 ?
缓存雪崩意思是设置缓存时采用了相同的过期时间,导致缓存在某一时刻同 时失效,请求全部转发到DB,DB 瞬时压力过重雪崩。与缓存击穿的区别: 雪崩是很多key,击穿是某一个key缓存。 解决方案主要是可以将缓存失效时间分散开,比如可以在原有的失效时间基 础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重 复率就会降低,就很难引发集体失效的事件。
- redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)
我们采用的是redisson实现的读写锁,在读的时候添加共享锁,可以保证读 读不互斥,读写互斥。当我们更新数据的时候,添加排他锁,它是读写,读 读都互斥,这样就能保证在写数据的同时是不会让其他线程读数据的,避免 了脏数据。这里面需要注意的是读方法和写方法上需要使用同一把锁才行。
面试官:那这个排他锁是如何保证读写、读读互斥的呢?
候选人:其实排他锁底层使用也是setnx,保证了同时只能有一个线程操作 锁住的方法
面试官:你听说过延时双删吗?为什么不用它呢?
候选人:延迟双删,如果是写操作,我们先把缓存中的数据删除,然后更新 数据库,最后再延时删除缓存中的数据,其中这个延时多久不太好确定,在 延时的过程中可能会出现脏数据,并不能保证强一致性,所以没有采用它。
- redis做为缓存,数据的持久化是怎么做的?
1、RDB 2、AOF
7.RDB是一个快照文件,它是把redis内存存储的数据写到磁盘上,当 redis实例宕机恢复数据的时候,方便从RDB的快照文件中恢复数据。
RDB因为是二进制文件,在保存的时候体积也是比较小的,它恢复 的比较快,但是它有可能会丢数据,我们通常在项目中也会使用AOF来恢复 数据,虽然AOF恢复的速度慢一些,但是它丢数据的风险要小很多,在AOF 文件中可以设置刷盘策略,我们当时设置的就是每秒批量写入一次命令
8.这两种方式,哪种恢复的比较快呢?
RDB因为是二进制文件,在保存的时候体积也是比较小的,它恢复 的比较快,但是它有可能会丢数据,我们通常在项目中也会使用AOF来恢复 数据,虽然AOF恢复的速度慢一些,但是它丢数据的风险要小很多,在AOF 文件中可以设置刷盘策略,我们当时设置的就是每秒批量写入一次命令
8.Redis的数据过期策略有哪些 ?
第一种是惰性删除,在设置该key过期时间后,我们不去管它,当需要该key 时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。 第二种是 定期删除,就是说每隔一段时间,我们就对一些key进行检查,删 除里面过期的key 定期清理的两种模式: SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配 置文件redis.conf 的 hz 选项来调整这个次数 FAST模式执行频率不固定,每次事件循环会尝试执行,但两次间隔不低于2ms, 每次耗时不超过1ms
Redis的过期删除策略:惰性删除 + 定期删除两种策略进行配合使用。
9.Redis的数据淘汰策略有哪些 ?
这个在redis中提供了很多种,默认是noeviction,不删除任何数据,内 部不足直接报错是可以在redis的配置文件中进行设置的,里面有两个非常重要的概念,一个 是LRU,另外一个是LFU LRU的意思就是最少最近使用,用当前时间减去最后一次访问时间,这个值 越大则淘汰优先级越高。 LFU的意思是最少频率使用。会统计每个key的访问频率,值越小淘汰优先级 越高 我们在项目设置的allkeys-lru,挑选最近最少使用的数据淘汰,把一些经常 访问的key留在redis中
10.数据库有1000万数据 ,Redis只能缓存20w数据, 如何保证Redis中的 数据都是热点数据 ?
可以使用 allkeys-lru (挑选最近最少使用的数据淘汰)淘汰策略,那留下来 的都是经常访问的热点数据
11.Redis的内存用完了会发生什么?
这个要看redis的数据淘汰策略是什么,如果是默认的配置,redis内存 用完以后则直接报错。我们当时设置的 allkeys-lru 策略。把最近最常访问的 数据留在缓存中。
12.Redis分布式锁如何实现 ?
由于redis的单线程的,用了命令之后,只能有一个客户端对某一个key设置 值,在没有过期或删除key的时候是其他客户端是不能设置这个key的
13.Redis集群有哪些方案, 知道嘛 ?
候选人:嗯~~,在Redis中提供的集群方案总共有三种:主从复制、哨兵模 式、Redis分片集群
14.Redis是单线程的,但是为什么还那么快?
1、完全基于内存的,C语言编写
2、采用单线程,避免不必要的上下文切换可竞争条件
3、使用多路I/O复用模型,非阻塞IO
例如:bgsave 和 bgrewriteaof 都是在后台执行操作,不影响主线程的正常 使用,不会产生阻塞