2021年有哪些Redis高频面试题

发布时间:2021-10-18 10:35:47 作者:柒染
来源:亿速云 阅读:168

本篇文章给大家分享的是有关2021年有哪些Redis高频面试题,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

2021年有哪些Redis高频面试题

面试官心理分析

从面试官的角度分析,出这道题的目的是为了考察你对缓存的认知水平,以及结合缓存处理业务、改善架构的能力。这道题很明显是让你自由发挥,给了你引领面试官往自己最熟悉的知识点引导的机会,所以要尽可能的把握这次机会,给面试官一个好的印象。这道题聊得好,就是能深入交流个把小时了,如果是一面基本上能轻轻松松拿下。【相关推荐:Redis视频教程】

但是千万不要上来就把话题聊死了,聊太浅了, 那基本就是回去等通知了……


比如以下这种回答方式:

2021年有哪些Redis高频面试题

很多人会说这么回答也没错呀!没错是没错,但是总有一种给你机会不中用的感觉。

此时此刻面试官内心想发大致是这样的:

如果不想硬抗下面试官的降龙十八掌,就应该主动挑起面试官的兴趣,并且把自己的格局(水平广度和深度)率先提升起来,将自己会的东西尽可能的多讲一些出来。

比如以下这种回答方式:

2021年有哪些Redis高频面试题

Redis面试题汇总

2021年有哪些Redis高频面试题

这个我的理解大致是这样的面试官!!

高性能:高性能一个很大的标准,就是响应时间快。Redis基于内存存储,CPU访问速度快,此外Redis对于数据结构的极致优化、内部线程模型和网络I/O模型的设计,决定了Redis是一个高性能存储数据库。唯一的缺点就是内存比较昂贵,通常情况下资源比较有限,因此对于非常大的数据缓存架构应该合理设计,我们通常不会在Redis中存放过大的数据,因为这样会导致Redis性能下降。

高并发:高并发通常指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second)和并发用户数等,Redis虽然它是一个单进程单线程模型,但是Redis确实高并发业务场景下的一把利器,目前Redis的QPS已经能达到10万甚至是100万级别了,这是绝对的高并发。

高可用:Redis高可用主要体现在主从复制、sentinel(哨兵模式)和Cluster(集群模式)三者

2021年有哪些Redis高频面试题

这个我的理解大致是这样的面试官!!

Redis的单线程指的是执行命令操作使用单线程,Redis6.x发布之后使用多线程处理网络数据的读写和协议解析,Redis单线程这么快的原因主要有这些点:

2021年有哪些Redis高频面试题

这个我的理解大致是这样的面试官!!

Redis有5种基本数据类型它们分别是String、List、Hash、Set、ZSet;此外还有三种特殊数据类型Bitmaps、Geospatial、HyperLogLog

数据类型简单描述使用场景
Stringstring(字符串)是Redis最简单也是使用最广泛的数据结构,它的内部是一个字符数组。String(字符串)是动态字符串,允许修改;它在结构上的实现类似于Java中的ArrayList(默认构造一个大小为10的初始数组),这是冗余分配内存的思想,也称为预分配;这种思想可以减少扩容带来的性能消耗。当string(字符串)的大小达到扩容阈值时,将会对string(字符串)进行扩容,string(字符串)的扩容主要有三种情况:1.长度小于1MB,扩容后为原先的两倍; length = length * 2 2.长度大于1MB,扩容后增加1MB; length = length + 1MB 3. 字符串的长度最大值为 512MB缓存、计数器、分布式锁等。
ListRedis的列表相当于Java语言中的LinkedList,它是一个双向链表数据结构(但是这个结构设计比较巧妙,后面会介绍),支持前后顺序遍历。链表结构插入和删除操作快,时间复杂度O(1),查询慢,时间复杂度O(n)。Redis的list(列表)不是一个简单。LinkedList,而是quicklist ——“快速列表”,quicklist是多个ziplist(压缩列表)组成的双向列表;链表、异步队列、微博关注人时间轴列表……
HashRedis的hash(字典)相当于Java语言中的HashMap,它是根据散列值分布的无序字典,内部的元素是通过键值对的方式存储。hash(字典)的实现与Java中的HashMap(JDK1.7)的结构也是一致的,它的数据结构也是数组+链表组成的二维结构,节点元素散列在数组上,如果发生hash碰撞则使用链表串联在数组节点上。Redis中的hash(字典)存储的value只能是字符串值,此外扩容与Java中的HashMap也不同。Java中的HashMap在扩容的时候是一次性完成的,而Redis考虑到其核心存取是单线程的性能问题,为了追求高性能,因而采取了渐进式rehash策略。渐进式rehash指的是并非一次性完成,它是多次完成的,因此需要保留旧的hash结构,所以Redis中的hash(字典)会存在新旧两个hash结构,在rehash结束后也就是旧hash的值全部搬迁到新hash之后,新的hash在功能上才会完全替代以前的hash。用户信息、Hash 表……
SetRedis的set(集合)相当于Java语言里的HashSet,它内部的键值对是无序的、唯一的。它的内部实现了一个所有value为null的特殊字典。集合中的最后一个元素被移除之后,数据结构被自动删除,内存被回收。去重功能、赞、踩、共同好友……
ZSetzset(有序集合)是Redis中最常问的数据结构。它类似于Java语言中的SortedSet和HashMap的结合体,它一方面通过set来保证内部value值的唯一性,另一方面通过value的score(权重)来进行排序。这个排序的功能是通过Skip List(跳跃列表)来实现的。zset(有序集合)的最后一个元素value被移除后,数据结构被自动删除,内存被回收。粉丝列表、学生成绩排序、访问量排行榜、点击量排行榜……
BitmapsBitmaps 称为位图,严格来说它不是一种数据类型。Bitmaps底层就是字符串(key-value)byte数组。我们可以使用普通的get/set直接获取和设值位图的内容,也可以通过Redis提供的位图操作getbit/setbit等将byte数组看成“位数组”来处理。Bitmaps 的“位数组”每个单元格只能存储0和1,数组的下标在Bitmaps中称为偏移量。Bitmaps设置时key不存在会自动生成一个新的字符串,如果设置的偏移量超出了现有内容的范围,就会自动将位数组进行零扩充员工打卡……
GeospatialGeospatial是Redis在3.2版本以后增加的地理位置GEO模块微信附近的人,在线点餐“附近的餐馆”……
HyperLogLogHyperLogLog是用来做基数统计的算法,它提供不精确的去重计数方案(这个不精确并不是非常不精确),标准误差是0.81%,对于UV这种统计来说这样的误差范围是被允许的。HyperLogLog的优点在于,输入元素的数量或者体积非常大时,基数计算的存储空间是固定的。在Redis中,每个HyperLogLog键只需要花费12KB内存,就可以计算接近2^64个不同的基数。但是HyperLogLog只能统计基数的大小(也就是数据集的大小,集合的个数),他不能存储元素的本身,不能向set集合那样存储元素本身,也就是说无法返回元素。基数统计比如UV等

2021年有哪些Redis高频面试题

这个我的理解大致是这样的面试官!!

Redis的数据结构均可以通过EXPIRE key seconds 的方式设置key的过期时间(TTL)。我们也习惯的认为Redis的key过期时间到了,就会自动删除,显然这种想法并不正确。Redis的设计考虑到性能/内存等综合因素,设计了一套过期策略。

主动删除(惰性删除)指的是当key被访问的时候,先校验key是否过期,如果过期了则主动删除。

被动删除(定期策略)指的是Redis服务器定时随机的测试key的过期时间,如果过期了则被动删除。被动删除的存在必不可少,因为存在一些过期且永久不在访问的key,如果都依赖主动删除,那么它们将会永久占用内存。

Redis为了保证提供高性能服务,被动删除过期的key,采用了贪心策略/概率算法,默认每隔10秒扫描一次,具体策略如下:

此外开发在设计Redis缓存架构时,一定要注意要尽可能的避免(禁止)将大量的key设置为同一过期时间,因为结合被动删除可知,Redis被动删除过期key时,会导致服务短暂的不可用;如果存在大量key同时过期,这会导致被动删除key的三个步骤循环多次,从而导致Redis服务出现卡顿情况,这种情况在大型流量项目是无法接收的。

因此为了避免这种情况出现,一定要将一些允许过期时间不需要非常精确的key,设置较为随机的过期时间,这样就可以将卡顿时间缩小。

2021年有哪些Redis高频面试题

这个我的理解大致是这样的面试官!!

在分布式场景中我们常见的分布式锁解决方案有(如果自己都会可以把其他两种也在这带出来,如果不会那就别把自己坑了呀!):

而关于Redis实现分布式锁的方案是这样的。

如果Redis是在单机环境中, 我们可以通过,Redis提供的原子指令来实现分布式锁

set key value [EX seconds] [PX milliseconds] [NX|XX]

为了防止A加的锁,被B删除了,可以加锁时传入客户端加锁标记,只有当客户端传入的标记和锁标记相同时才允许解锁,不过Redis并未提供这样的功能,我们只能通过Lua脚本来处理,因为Lua脚本可以保证多个指令的原子性执行。最后我们还要考虑锁的超时问题,如果客户端一直不释放锁肯定也是不行的,因此锁只能保证在指定的超时时间范围内不被其他客户端解锁,超时之后就自动释放了,这种情况很难我们可以这样优化:

如果是在分布式环境中, 会增加一个新的问题,比如sentinel+一主多从环境中,可能存在客户端在主节点上申请了锁,但是同步未完成,主节点宕机了,此时新选举的主节点上锁是失效的。

对于这种情况的处理应该是这么考虑的,首先Redis主从同步直接无论如何都无法解决数据会有丢失的情况。所以我们考虑把像一个Redis申请锁,变成像多个单机Redis申请锁,只有大部分申请成功就行。这种思想就是RedLock(红锁)。

RedLock通过使用多个Redis实例,各个实例之间没有主从关系,相互独立;加锁的时候,客户端向所有的节点发送加锁指令,如果过半的节点set成功,就加锁成功。释放锁时,需要向所有的节点发送del指令来释放锁。

红锁虽然解决了主从同步的问题,但是带来新的复杂问题:

因此在RedLock中需要计算申请的锁的最小有效时长。假设客户端申请锁成功,第一个key设置成功的时间为TF,最后一个key设置成功的时间为TL,锁的超时时间为TTL,不同进程之间的时钟差异为CLOCK_DIFF,则锁的最小有效时长是:

TIME = TTL - (TF- TL) - CLOCK_DIFF

采用Redis来实现分布式锁,离不开服务器宕机等不可用问题,这里RedLock红锁也一样,即使是多台服务器申请锁,我们也要考虑服务器宕机后的处理,官方建议采用AOF持久化处理。

但是AOF持久化只对正常SHUTDOWN这种指令能做到重启恢复,但是如果是断电的情况,可能导致最后一次持久化到断电期间的锁数据丢失,当服务器重启后,可能会出现分布式锁语义错误的情况。所以为了规避这种情况,官方建议Redis服务重启后,一个最大客户端TTL时间内该Redis服务不可用(不提供申请锁的服务),这确实可以解决问题,但是显而易见这肯定影响Redis服务器的性能,并且在多数节点都出现这种情况的时候,系统将出现全局不可用的状态。

2021年有哪些Redis高频面试题

这个我的理解大致是这样的面试官!!

Redis的非常快,很大一部分原因是因为Redis的数据存储在内存中,既然在内存中,那么当服务器宕机或者断电的时候,数据就会全部丢失了,所以Redis提供了两种机制来保证Redis数据不会因为故障而全部丢失,这种机制称为Redis的持久化机制。

Redis的持久化机制有两种:

RDB(Redis DataBase) 指的是在指定的时间间隔内将内存中的数据集快照写入磁盘,RDB是内存快照(内存数据的二进制序列化形式)的方式持久化,每次都是从Redis中生成一个快照进行数据的全量备份。

优点:

缺点:

RDB触发的规则分为两大类,分别是手动触发和自动触发:

自动触发:

手动触发:

AOF(Append Only File) 是把所有对内存进行修改的指令(写操作)以独立日志文件的方式进行记录,重启时通过执行AOF文件中的Redis命令来恢复数据。AOF能够解决数据持久化实时性问题,是现在Redis持久化机制中主流的持久化方案(后续会谈到4.0以后的混合持久化)。

优点:

缺点:

AOF日志是以文件的形式存在的,当程序对AOF日志文件进行写操作时,实际上将内容写到了内核为文件描述符分配的一个内存缓冲区中,随后内核会异步的将缓冲区中的数据刷新到磁盘中。如果缓冲区中的数据没来得及刷回磁盘时,服务器宕机了,这些数据就会丢失。

因此Redis通过调用Linux操作系统的glibc提供的fsync(int fid)来将指定文件的内容强制从内核缓冲区刷回磁盘,以此来保证缓冲区中的数据不会丢失。不过这是一个IO操作,相比Redis的性能来说它是非常慢的,所以不能频繁的执行。

Redis配置文件中有三种刷新缓冲区的配置:

appendfsync always

每次Redis写操作,都写入AOF日志,这种配置理论上Linux操作系统扛不住,因为Redis的并发远远超过了Linux操作系统提供的最大刷新频率,就算Redis写操作比较少的情况,这种配置也是非常耗性能的,因为涉及到IO操作,所以这个配置基本上不会用

appendfsync everysec

每秒刷新一次缓冲区中的数据到AOF文件,这个Redis配置文件中默认的策略,兼容了性能和数据完整性的折中方案,这种配置,理论上丢失的数据在一秒钟左右

appendfsync no

Redis进程不会主动的去刷新缓冲区中的数据到AOF文件中,而是直接交给操作系统去判断,这种操作也是不推荐的,丢失数据的可能性非常大。

前面提到AOF的缺点时,说过AOF属于日志追加的形式来存储Redis的写指令,这会导致大量冗余的指令存储,从而使得AOF日志文件非常庞大,这种情况不仅占内存,也会导致恢复的时候非常缓慢,因此Redis提供重写机制来解决这个问题。Redis的AOF持久化机制执行重写后,保存的只是恢复数据的最小指令集,我们如果想手动触发可以使用如下指令

bgrewriteaof

Redis4.0后的重写使用的是RDB快照和AOF指令拼接的方式,在AOF文件的头部是RDB快照的二进制形式的数据,尾部是快照产生后发生的写入操作的指令。

由于重写AOF文件时,会对Redis的性能带来一定的影响,因此也不能随便的进行自动重写,Redis提供两个配置用于自动进行AOF重写的指标,只有这两个指标同时满足的时候才会发生重写:

auto-aof-rewrite-percentage 100:指的是当文件的内存达到原先内存的两倍

auto-aof-rewrite-min-size 64mb:指的是文件重写的最小内存大小

此外Redis4.0后大部分的使用场景都不会单独使用RDB或者AOF来做持久化机制,而是兼顾二者的优势混合使用。

最后来总结这两者,到底用哪个更好呢?

2021年有哪些Redis高频面试题

这个我的理解大致是这样的面试官!!

Redis是基于内存存储的key-value数据库,我们知道内存虽然快但空间小,当物理内存达到上限时,系统就会跑的很慢,所以我们会设置Redis的最大内存,当Redis内存达到设定阈值的时候会触发内存回收,Redis提供了很多内存淘汰策略:

在这些策略中有两个比较重要的算法一个是LRU,也就是淘汰最近最少使用的key。不过Redis使用了近似LRU算法,并不是完完全全准确的淘汰掉最近最不经常使用的key,但是总体的准确度也可以得到保证。

近似LRU算法非常简单,在Redis的key对象中,增加24bit用于存储最近一次访问的系统时间戳,当客户端对Redis服务端发送key的写入相关请求时,发现内存达到maxmemory,此时触发惰性删除;Redis服务通过随机采样,选择5个满足条件的key(注意这个随机采样allkeys-lru是从所有的key中随机采样,volatile-lru是从设置了过期时间的所有key中随机采样),通过key对象中记录的最近访问时间戳进行比较,淘汰掉这5个key中最旧的key;如果内存仍然不够,就继续重复这个步骤。

在Redis 3.0 maxmemory_samples设置为10的时候,Redis的近似LRU算法已经非常的接近真实LRU算法了,但是显然maxmemory_samples设置为10比maxmemory_samples 设置为5要更加消耗CPU计算时间,因为每次采样的样本数据增大,计算时间也会增加。

Redis3.0的LRU比Redis2.8的LRU算法更加准确,是因为Redis3.0增加了一个与maxmemory_samples相同大小的淘汰池,每次淘汰key的时候,先与淘汰池中等待被淘汰的key进行比较,最后淘汰掉最老旧的key,其实就是被选中淘汰的key放到一起再比较一下,淘汰其中最旧的。

LRU有一个明显的缺点,它无法正确的表示一个Key的热度,如果一个key从未被访问过,仅仅发生内存淘汰的前一会儿被用户访问了一下,在LRU算法中这会被认为是一个热key。LFU(Least Frequently Used)是Redis 4.0 引入的淘汰算法,它通过key的访问频率比较来淘汰key,重点突出的是Frequently Used。

LRU与LFU的区别:

在LFU模式下,Redis对象头的24bit lru字段被分成两段来存储,高16bit存储ldt(Last Decrement Time),低8bit存储logc(Logistic Counter)。高16bit用来记录最近一次计数器降低的时间,由于只有8bit,存储的是Unix分钟时间戳取模2^16,16bit能表示的最大值为65535(65535/24/60≈45.5),大概45.5天会折返(折返指的是取模后的值重新从0开始)。

低8位用来记录访问频次,8bit能表示的最大值为255,logc肯定无法记录真实的Rediskey的访问次数,其实从名字可以看出存储的是访问次数的对数值,每个新加入的key的logc初始值为5(LFU_INITI_VAL),这样可以保证新加入的值不会被首先选中淘汰;logc每次key被访问时都会更新;此外,logc会随着时间衰减。

Logistic Counter不仅会增长,也会衰弱,增长和衰弱的规则也可以通过redis.conf进行配置。

2021年有哪些Redis高频面试题

这个我的理解大致是这样的面试官!!

缓存击穿:

就是说某个访问非常频繁的热点 key ,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,直接穿过了Redis。

解决方式:

缓存穿透:

指的是缓存和数据库中都不存在的数据被请求,这种情况通常是被黑客攻击力,如果不做好防御很容易导致数据库被请求打死。比如黑客使用负数id查询你的某个表,我们的id通常不会设置为负数。

解决方式:


缓存雪崩:

缓存雪崩发生在大量缓存同时失效的情况,会导致数据库瞬间崩溃(高并发场景),而且这种情况下如果缓存不恢复,数据库起来也没用,还是会继续被打崩。

解决方式:

2021年有哪些Redis高频面试题

差不多回答到这里,面试官的脸色露出了久违的微笑,我们接下来只有接住这一招,这次面试就有了。

当然关于这个知识点不是几句话能说清楚的,所以建议大家看看这篇文章,就可以轻松hold住了

以上就是2021年有哪些Redis高频面试题,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

推荐阅读:
  1. Python有哪些高频面试题
  2. 熟悉这几道 Redis 高频面试题,面试不用愁

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

redis

上一篇:如何更改centos的php版本

下一篇:在本地端口33061上打开到slave1:33061的连接时出错该怎么办

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》