Redis 面试知识点

1、Redis缓存数据库一致性

  采用最终一致性,而不是采用强一致性,强一致性会导致系统吞吐量变差;采用双删除的策略,第二次删除,采用延迟删除;

  推荐采用,先操作数据库,直接删除缓存的方式;

  删除失败的情况,采用异步方式,重试操作;

  读取binlog异步删除,使用开源框架canal,监听canal通知消息,当收到变化的消息时,完成对缓存的更新。主要用于数据库增量日志解析,提供增量数据订阅和消费;

2、Redis 单线程为什么这么快

  Redis 基于Reactor模式开发了网络事件处理器,I/O 多路复用机制来同时监听多个Socket,根据Socket上的事件类型来选择对应的事件处理器来处理这个事件。可以实现高性能的网络通信模型。多个Socket 可能并发的产生不同的事件;通过排队操作,解决问题;

  单线程快的原因:

  (1)纯内存操作;

  (2)核心是基于非阻塞的IO多路复用机制;

  (3)单线程反而避免了多线程的频繁上下文切换带来的性能问题;

3、Redis 击穿、雪崩、穿透;

(1)缓存击穿。高并发时,当某一个key 非常热点(类似于爆款)。在不停的扛着大并发,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库并设置到缓存中,导致性能下降;

  解决办法:(1)永不过期;(2)加锁排队;

  当Redis缓存失效,采用同步锁Synchronized() ,读取数据库,并且更新Redis;

(2)缓存雪崩:缓存集中过期,或者缓存服务器宕机,导致大量请求访问数据库,造成数据库,瞬间压力过大,宕机;

  解决办法:(1)加锁排队;(2)随机失效时间;(3)redis高可用;

(3)缓存穿透:数据库不存在缓存中也不存在,导致每次请求都回去查询数据库,这时的用户很有可能是攻击者,如发起为id为“-1”的数据或者id为特别大(不存在的数据),导致数据库过大或宕机;

  解决方法:(1)参数校验;(2)缓存空对象;(3)布隆过滤器;是一种高效的数据结构;

4、分布式锁

  通过Redis 的 SetNX实现分布式锁;

  解决:Redisson;UUID,加锁; red lock();

5、Redis的过期键的删除策略;

(1)惰性过期:只有当访问一个key时,才会判断该key是否已经过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况。存在大量的过期key没有再次被访问,从而不会被清除,占用大量内存;

(2)定期过期:每隔一段的事件,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果;

  Redis中同时使用了惰性过期和定期过期两种过期策略;

6、Redis分布式锁底层是如何实现的?

(1)首先利用setnx来保证 : 如果key不存在才能获取到锁,如果key存在,则获取不到锁
(2)然后还要利用lua脚本来保证多个redis操作的原子性
(3)同时还要考虑到锁过期,所以需要额外的一个看门狗定时任务来监听锁是否需要续约
(4)同时还要考虑到redis节点挂掉后的情况,所以需要采用红锁的方式来同时向 N/2 + 1个节点申请锁,都申请到了才证明获取锁成功,这样就算其中某个redis节点挂掉了,锁也不能被其他客户端获取到;

7、Redis底层数据是如何用跳表来存储的?

   跳表(有序集合 Z - Set):将有序链表改造为支持近似“折半查找”算法,可以进行快速的插入、删除、查找操作;

8、Redis Key过期了,为什么内存没有释放?

  使用 SET 设置过期时间。 如果没有加上 EX 时间。则设置为永久不过期;

  因此,在使用SET命令时,如果刚开始就设置了过期时间,那么之后修改这个Key值,也务必加上过期时间的参数,避免过期时间丢失问题;

9、Redis Key 没有设置过期时间,为什么被Redis主动删除了

  当Redis已用内存超过maxmemory限定时,触发主动清除策略;

  主动清除策略在Redis 4.0 之前一共实现了6中内存淘汰策略,在4.0之后,又增加了2种策略,总共8种:

  1)针对设置了过期时间的Key做处理:

  (1)volatile - ttl : 在筛选时,会针对设置了过期时间的键值对,根据过期时间的先后进行删除,越早过期的越先被删除。

  (2)volatile-random:就像它的名称一样,在设置了过期时间的键值对中,进行随机删除。

  (3)volatile-lru:会使用 LRU 算法筛选设置了过期时间的键值对删除。

  (4)volatile-lfu:会使用 LFU 算法筛选设置了过期时间的键值对删除。

  2)针对所有的Key做处理:

  (5)allkeys-random : 从所有键值对中随机选择并删除数据。

  (6)allkeys-lru : 使用 LRU 算法在所有数据中进行筛选删除;

  (7)allkeys-u : 使用 LFU 算法在所有数据中进行筛选删除;

  3)不处理:

  (8)noeviction : 不会剔除任何数据,拒绝所有写入操作并返回客户端错误信息"(error) OOM command not alowed when used memory",此时Redis只响应读操作。

10、Redis 淘汰Key的算法LRU与LFU区别:

  首先介绍一下,LRU 和 LFU :

  (1)LRU算法(Least Recently Used,最近最少使用):淘汰很久没有被访问过的数据,以最近一次访问时间为参考;

  (2)LFU算法(Least Frequently Used,最不经常使用):淘汰最近一段时间被访问次数最少得数据,以次数作为参考;

  当存在大量的热点缓存数据时,LFU可能会更好点;

11、删除Key的命令会阻塞Redis吗?

  时间复杂度:

  删除单个字符串类型的key,时间复杂度O(1);

  删除单个集合、列表。时间为O(M),M为长度;

12、Redis 主从、哨兵、集群架构优缺点比较

(1)主从节点 master 主节点;slave 从节点;

(2)哨兵

(3)集群

  redis集群是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群不需要sentinel哨兵·也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。redis集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。

13、Redis集群数据Hash分片算法是怎么回事?

  槽位定位算法:16384个槽位;用模的方式,进行运算,从而分配到各个位置上;

14、Redis执行命令有死循环阻塞BUG

  想要随机查看Redis里面的一个Key,Redis里面存在RANDOMKEY 方法,可以随机取出一个Key,这个命令会导致Redis死循环阻塞;

  Slave ,随机出现一个Key,判断是否过期;有可能会导致整个Redis实例卡死;

  解决办法:slave查找一定次数,无论是否找到,都要退出循环;

15、一次线上事故,Redis主从切换导致了缓存雪崩

  我们假设,slave 的机器时钟比 master 走得快很多。

  此时,Redis master里设置了过期时间的key,从 slave 角度来看,可能会有很多在 iast6r里没过期的数据其实已经过期了。

  如果此时操作主从切换,把 slave 提升为新的 master。它成为 master 后,就会开始大量清理过期 key,此时就会导致以下结果:

  (1)master 大量清理过期 key,主线程可能会发生阻塞,无法及时处理客户端请求。

  (2)Redis 中数据大量过期,引发缓存雪崩。

  当 master与slave 机器时钟严重不一致时,对业务的影响非常大,所以,我们一定要保证主从库的机器时钟一致性,避免发生这些问题;

16、Redis持久化RDB、AOF、混合持久化是怎么回事

  (1)RDB 快照:

    save 60 900,60秒内最少修改900次,将所有的Redis内存快照自动保存到RDB文件中;

    save和bgsave 区别:

    (1)save 通过主线程执行;同步操作;

    (2)bgsave 异步操作;不阻塞客户端命令;bgsave的写实复制COW机制;如果主线程修改一块数据,那么,这块数据就会被复制一份,生成该数据的副本;

  (2)AOF持久化:

    AOF持久化,将修改的每一条指令记录写入aof文件中。每当Redis执行一个改变数据集的命令时,命令会被追加到AOF文件的末尾;

    AOF重写redis会fork出一个子进程去做,不会对redis正常命令处理有太多影响;

    appendfsync everysec:每秒fsync一次,足够快,并且在故障时只会丢失1秒的数据;数据安全性比RDB更好;

    优化机制:AOF重写;

       1)auto-rewrite-min-size 64mb:至少达到64MB才会自动重写;

       2)rewrite-percentage 100 :增长100%,再次触发重写机制;

     默认采用AOF恢复数据;一般来说,aof数据更加安全一点;但是aof日志性能相对来说慢一些;

  (3)混合持久化(必须先开启aof)

    如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转化为RESP命令写入AOF文件,而是重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入到新的AOF文件,新的文件一开始不叫aof,等到重写完新的AOF文件才会进行改名,覆盖到原有的AOF文件,完成新旧两个AOF文件的替换。

    因此,在Redis重启的时候,可以先加载RDB的内容,然后再重新增量AOF日志来完全替换之间的AOF全量文件重放,因此,重启效率大幅度得到提升;

17、线上Redis持久化策略一般如何设置

   如果对性能要求较高,在Master最好不要做持久化,可以在某个Slave开启AOF备份数据,策略设置为每秒同步一次即可。

18、一次线上事故,Redis主节点宕机导致数据全部丢失(略)

19、Redis线上数据如何备份

(1)写crontab定时调度脚本,每小时copy一份RDB或者AOF文件到另外一台机器中,保存最近48小时的备份;

(2)每天都保留一份当日的数据备份到一个目录中去,可以保留最近1个月的备份;

(3)每次copy备份的时候,都把太旧的备份给制了

20、Redis主从复制风暴

  含义:某一时刻如果所有从节点都同时连接主节点,那么主节点会同时把内存快照RDB发送给从节点,这样会导致Redis主节点压力非常大;

  解决方法:可以采用树形复制架构。将原本属于主节点的从节点,连接到从节点上;

21、底层存储架构分析:

(1)String应用场景:

  1)计数器:访问次数;序列号自动增加;

  2)共享session

(2)Hash应用场景:

  购物车,增加、减少商品个数;

(3)List应用场景:

  微博和微信公号消息流

(4)Set应用场景:

  1)微信抽奖小程序

  2)微信微博点赞,收藏,标签;

  3)集合操作实现微博微信关注模型

(5)有序集合Zset:

  1)排行榜; 

posted @ 2024-04-25 20:47  我太想努力了  阅读(6)  评论(0编辑  收藏  举报