/ 面经 / 19浏览

Redis 面试题

Redis高性能如何实现

  • 基于单线程实现,避免多线程带来的线程切换开销,单线程中使用IO多路复用处理并发
  • 大部分操作基于内存,读写操作不需要磁盘IO
  • 采取简单的数据结构,例如跳表、哈希表

为什么不采用多进程或多线程处理?

多线程处理可能涉及到锁
多线程处理会涉及到线程切换而消耗CPU

IO多路复用是什么概念

单线程 不堵塞 性能还是高效呢 服务只有一个线城 多个请求 效率如何达到的 一个线城如何处理n多个线城

有序集合Zset

redis中的有序集合通过skiplist即跳表来实现集合的插入、删除、快速查找

zSet是什么数据结构 实现的具体数据结构是什么 跳表 跳表又是什么样的数据结构

跳表节点的插入和删除,可能使得两个索引点之间存在大量的节点,极端情况下,退化为单链表,如何解决这种情况?
简单的讲,就是引入一个随机函数,新插入的节点有一定的概率随机插入某一层的索引链表中

image-1650001237288

字符串

redis中字符串的实现为 :SDS 简单动态字符串
其实现特点是:空间预分配和惰性删除(与STL中Vector的空间分配机制类似)
即通过三指针确定分配的空间以及空间的使用情况

struct sdshdr{
    //字符串长度
    int len;
    //当前空间的总长度
    int capacity;
    //指向字符数组首地址
    char* buf;
};

预先分配原则:当存储一定长度的字符串时,会预先申请比字符串长度更大的空间
惰性删除原则:当字符串长度减少时,不会释放空间,而只是在len中做修改

字典(哈希表)

redis中dict字典是其核心的实现,采取hash[2]即两张hash表来进行优化
基于key运行hash函数获得hash值
根据hash值对hash表长度取模,确定存放的bucket位置
将键值对根据bucket索引值存放在对应位置

如何解决hash冲突,即不同的key对应到同一个索引值?

采取链地址法,即数组+链表的方式,冲突的键值对存放在同一个链表中

双hash表的作用:高效实现rehash

什么时候需要rehash?

当hash表中负载因子loadfactor超过一定上限时,需要对hash表进行扩容,那么相应的键值对的取模索引值会发生变化,需要进行rehash

  • 所有的数据原先存放在hash表1中,当需要rehash时,hash表2的空间调整为对应原先空间的两倍
  • 将hash表1的键值对,执行rehash操作,移动到hash表2,这里会采取渐进式hash进行优化。
  • 当hash表1的所有键值对移动到hash表2时,释放hash表1,修改hash表2为hash表1

渐进式hash:将对每个键值对rehash的操作,分摊到对该键值对的查、删、改操作上,避免短时间内对大量键值对集中rehash的性能开销。

redis持久化

redis持久化方式:①RDB快照持久化 ②AOF命令持久化

RDB持久化:某个时间点通过对内存缓冲区的数据进行快照,写入RDB文件,主要分为save命令和bgsave命令,将键值对写入到文件中。服务器启动时,载入RDB文件即可。

AOF持久化:以文本形式将写命令整合到AOF文件中,当服务器启动时,重新执行AOF中的命令即可。AOF文件写入,会采取缓冲区的方式提高性能。即有关命令先写入到AOF.buf缓冲区,然后一定条件下分块写入AOF文件。

什么是AOF重写?

AOF文件随着服务器运行会不断增大,可以通过整合一些冗余的键值对操作,缩小AOF文件,减少空间占用。

1、什么是 Redis?

2、Redis 的数据类型?

3、使用 Redis 有哪些好处?

4、Redis 相比 Memcached 有哪些优势?

5、Memcache 与 Redis 的区别都有哪些?

6、Redis 是单进程单线程的?

7、一个字符串类型的值能存储最大容量是多少?

8、Redis 的持久化机制是什么?各自的优缺点?

9、Redis 常见性能问题和解决方案:

10、redis 过期键的删除策略?

11、Redis 的回收策略(淘汰策略)?

12、为什么 edis 需要把所有数据放到内存中?

13、Redis 的同步机制了解么?

答:Redis 可以使用主从同步,从从同步。第一次同步时,主节点做一次 bgsave,并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到复制节点,复制节点接受完成后将 rdb 镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

14、Pipeline 有什么好处,为什么要用 pipeline?

15、是否使用过 Redis 集群,集群的原理是什么?

16、Redis 集群方案什么情况下会导致整个集群不可用?

17、Redis 支持的 Java 客户端都有哪些?官方推荐用哪个?

18、Jedis 与 Redisson 对比有什么优缺点?

19、Redis 如何设置密码及验证密码?

20、说说 Redis 哈希槽的概念?

21、Redis 集群的主从复制模型是怎样的?

22、Redis 集群会有写操作丢失吗?为什么?

23、Redis 集群之间是如何复制的?

24、Redis 集群最大节点个数是多少?

25、Redis 集群如何选择数据库?

26、怎么测试 Redis 的连通性?

27、怎么理解 Redis 事务?

28、Redis 事务相关的命令有哪几个?
答:异步复制

redis过期数据删除的机制 删除的策略

实际项目中用到了redis哪些数据结构 用list做了什么

为什么用redis用来保存验证码

redis过期数据的处理

缓存(失效)击穿

大量的缓存在同一时间失效,这时候如果进来大量的请求,可能会造成数据库瞬间压力过大,甚至宕机。
解决方案:在设置缓存时,不要设置相同的失效时间,可以加上一个随机的时间,分散缓存的过期时间,防止短时间内大量缓存失效。

redis雪崩 击穿

Redis 的过期策略都有哪些?

Redis 过期策略是:定期删除+惰性删除

所谓定期删除,指的是 Redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

假设 Redis 里放了 10w 个 key,都设置了过期时间,你每隔几百毫秒,就检查 10w 个 key,那 Redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。注意,这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,那样就是一场性能上的灾难。实际上 Redis 是每隔 100ms 随机抽取一些 key 来检查和删除的。

但是问题是,定期删除可能会导致很多过期 key 到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个 key 的时候,Redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。

获取 key 的时候,如果此时 key 已经过期,就删除,不会返回任何东西。

但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 Redis 内存块耗尽了,咋整?

答案是:内存淘汰机制

内存淘汰机制

Redis 内存淘汰机制有以下几个:

  • noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧,实在是太恶心了。
  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。
  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的 key 给干掉啊。
  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key(这个一般不太合适)。
  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。