Redis面试题拆解与回答技巧

1:Redis有哪些数据结构,底层编码有哪几类?其中有序链表采用了哪些不同的编码?

回答技巧

①大部分面试者都能够回答出五种类型,我们可以适当扩展一下,将Redis另外的4种高级类型的用法提一下,展示出自己知识的全面性。

②对于底层编码可以挑选其中一种讲解其类型的不同点和转换的条件,如果只能指出来在Redis配置文件中能够更改转换条件更好

③重点将有序表中的跳跃表编码进行解释

1:数据结构

 

从上图我们可以看出,Redis基本的五大数据类型对应的底层数据结构。同时可以发现后面的四种集合类型都是有两种的实现方式。

2:编码方式

①String的编码方式分别为int、embstr和raw

int:当存储的字符串全是数字时,此时使用int方式来存储;

embstr:当存储的字符串长度小于44个字符时,此时使用embstr方式来存储;

raw:当存储的字符串长度大于44个字符时,此时使用raw方式来存储;

②Hash的编码方式分别为ziplist和hashtable

ziplist 编码的哈希对象使用压缩列表作为底层实现

hashtable 编码的哈希对象使用字典作为底层实现

③List的编码方式分别为 linkedList、zipList和quickList

linkedList是一个双向链表

ziplist为压缩列表

quickList为linkedList与zipList的混合体,综合了两者的优点

④Set的编码方式分别为 intset和hashtable

intset 编码的集合对象使用整数集合作为底层实现

hashtable 编码的集合对象使用字典作为底层实现

⑤ZSet的编码方式分别为 zipList和skipList

ziplist 编码的有序集合对象使用压缩列表作为底层实现

skiplist 编码的有序集合对象使用 zset 结构作为底层实现

3:有序链表的编码

上面对有序链表ZSet已经做了解释,采用了zipList和skipList

zipList编码格式

 skipList编码格式

 2:Redis单线程为什么那么快?请描述Redis的IO多路复用机制?

回答技巧

①回答此问题,可以考虑从3点来回答即可,依次是,单线程,基于内存,IO多路复用,大多数面试者只能够回答出前2种,因此我们可以前两点稍微解释一下,而把重点放在第三点对IO多路复用的解释。

②对于多路复用大部分面试者只知道其概念,将其原理不见得可以说清楚,包括一些面试者也不见得可以说清楚,我们回答的时候可以采用类比的方式解释就更好了。例如下面的方式

1:单线程

采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。

2:基于内存

完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。

3:IO多路复用

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。

4:类比解释多路复用

我们类比一个实例:在课堂上让全班30个人同时做作业,做完后老师检查,30个学生的作业都检查完成才能下课。如何在有限的资源下,以最快的速度下课呢?

第一种:安排一个老师,按顺序逐个检查。先检查A,然后是B,之后是C、D。。。这中间如果有一个学生卡住,全班都会被耽误。这种模式就好比,你用循环挨个处理socket,根本不具有并发能力。这种方式只需要一个老师,但是耗时时间会比较长。

第二种:安排30个老师,每个老师检查一个学生的作业。 这种类似于为每一个socket创建一个进程或者线程处理连接。这种方式需要30个老师(最消耗资源),但是速度最快。

第三种:安排一个老师,站在讲台上,谁解答完谁举手。这时C、D举手,表示他们作业做完了,老师下去依次检查C、D的答案,然后继续回到讲台上等。此时E、A又举手,然后去处理E和A。这种方式可以在最小的资源消耗的情况下,最快的处理完任务。

3:请描述Redis拉链法解决全局哈希冲突的实现

回答技巧

①先以总结的方式回答解决的方法,例如:增加哈希桶的容量,减少哈希的冲突的概率,缩短链条的长度。

②再依次对总结的三句话进行拆解

1:全局哈希表

 

如上图所示,Redis是采用一个全局哈希表来存储键值对,全局哈希表又是由多个哈希桶组成,哈希桶中保存的是键值对的对应的指针。

因此在操作Redis的时候是通过哈希桶找到其对应的值得指针,进而进行下一步的增,删,查等操作。

2:数据量的增加

 

如上图所示,当随着Redis中存储的数据越来越多,则会出现同一个哈希桶对应多个entry,并且在数据结构上在每个entry后面都加上*next的指针,这样就形式了一个链表的方式存储数据。

这种方式的弊端会随着数据的增多,越来越明显,查询效率会越来越低。

3:解决方式

Redis此时就会对哈希表进行rehash操作,即重新hash,增加哈希桶的容量,减少哈希的冲突的概率,缩短链条的长度,从而达到redis的快速响应。

每次拷贝都是小部分的进行,避免了一次全量的拷贝造成线程的堵塞。

 4:什么叫Redis的索引?

回答技巧

①相信大家听的最多都是数据库索引,Mysql。此处提出一个Redis索引其实是有一种偷换概念的味道在里面,用这种方法来考察面试者对即熟悉又陌生的知识点如何面对

②对于此类问题,如果确实是不知道,可以很明确的说,没有接触过此类问题,但是可以尝试用自己的方法来实现该功能。然后结合自己熟悉的知识,我们也来一个偷换概念的方法,进而说出自己的思路,其实说的思路可以完全照帮熟悉知识中的方法,稍微做调整。

解答

Redis并不直接支持索引,实际上就是基于ZSet有序集合,由于其中有数值,数值就是索引,因此可以根据它找到其他值。

5:如何使用Redis解决缓存穿透?

回答技巧

①以总结的方式回答,面对这个问题,可以提供两种解决方案

②再依次对每种方法进行解释

1:缓存穿透的定义

key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。

2:解决方案

1:布隆过滤器

将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

关于布隆过滤器的原理,相信大家很熟悉,现在提供相关的文档,可以选择性进行阅读。

2:查询全部缓存

真实查询的数据缓存这个是必不可少的,如果一个查询返回的数据为空,无论是数据不存在,还是系统故障,仍然可以把这个空结果进行缓存,可以考虑将其过期时间设置的很短,超过五分钟之内,有效的避免缓存穿透。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要迷恋发哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值