当前位置:   article > 正文

Redis面试大全及答案_redis面试题大全含答案

redis面试题大全含答案

问1: 什么是缓存穿透

答:查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库

解决方案一:缓存空数据(优点:简单;缺点:消耗内存,可能发生数据不一致的问题)

解决方案二:布隆过滤器(优点:内存占用较少,没有多余key;缺点:实现复杂,存在误判)

问1: 什么是布隆过滤器

答:布隆过滤器主要是用于检索一个元素是否在一个集合中。

一般使用的是redisson实现的布隆过滤器。它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一开始都是0,当一个key来了之后经过3次hash计算,模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在。

问2: 什么是缓存击穿

答:给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮

解决方法一:缓存失效时先使用redis的setnx去设置一个互斥锁,成功去load db并回设缓存,否则重试get缓存的方法(强一致,性能差)

解决方法二:设置当前key逻辑过期,设置key时同时设置一个过期时间字段一块存入缓存中,查询时取出判断是否过期,如果过期则开通另一线程进行数据同步,当前线程正常返回旧数据(高可用,性能优,不能保证数据绝对一致)

问3: 什么是缓存雪崩

答:在同一时段大量的缓存key同时失效或者redis服务宕机,导致大量请求到达数据库,带来巨大压力

解决方法:将key的缓存失效时间分散开,可以在原有失效时间基础上增加一个随机值(设置redis集群,添加多级缓存Guava或Caffeine)

处理三大问题的保底策略:降级限流策略

问4: Redis的优缺点

答:优点:1、速度快:基于内存的数据库,读写速度非常快

2、支持多种数据结构:String(存储简单的字符串数据),List(存储有序的元素列表,支持排序和去重),Hash(存储对象和映射关系,哈希可以将一个对象的多个属性存储在一个键值对中,并且可以快速地根据某个属性进行查询),Set(存储不重复的元素集合),Zset(Sorted Set)(存储有序的元素集合)

3、高可用:支持主从复制,哨兵模式,集群

4、支持事务:保证一组操作的原子性

5、可扩展性:支持水平扩展,通过增加节点来提高系统的并发能力和存储能力

缺点:1、数据易丢失:如果服务器重启或关闭,数据将会丢失,需要使用持久化来保证数据的安全性

2、内存占用大:数据存储在内存中,数据量较大会占用较多的内存空间

3、不支持复杂查询:不支持复杂的查询操作,如关联查询,聚合查询等

4、性能受网络影响:如果网络延迟较大,可能会影响redis的性能

问5: Redis作为缓存,mysql的数据如何与redis进行同步(双写一致性)?

答:延迟双删:如果是写操作,会先把缓存中的数据删除,然后更新数据库,最后再延时删除缓存中的数据,由于不好确定延时多久,所以在延时的过程中可能会出现脏数据,并不能保证强一致性,一般不采用它。

解决方法一:允许延时一致(最终一致性)的业务,采用异步通知

① :使用MQ中间件,更新数据之后,通知缓存删除

② :利用canal(卡no)中间件,不需要修改业务代码,伪装为mysql的一个从节点,canal通过读取binlog数据更新缓存

解决方法二:允许强一致性的,采用Redisson(瑞迪森)提供的读写锁

① 共享锁:读锁readLock(瑞老科),加锁之后,其他线程可以共享读操作【读读不互斥,读写互斥】

② 排他锁:独占锁writeLock(r老科),底层使用的也是setnx(赛科斯),保证了同时只能有一个线程操作,加锁之后,阻塞其他线程读写操作【读写都互斥】

问6: redis作为缓存,数据的持久化是怎么做的?

答:解决方法一:RDB:(Redis Database Backup file)Redis数据备份文件,也叫Redis数据快照,把内存中的所有数据都记录到磁盘中,当Redis实例故障重启后,从磁盘读取快照文件,恢复数据

RDB执行原理:bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据,完成fork后读取内存数据并写入RDB文件

Fork采用的是copy-on-write技术:

① :当主进程执行读操作时,访问共享内存

② :当主进程执行写操作时,则会拷贝一份数据,执行写操作

解决方法二:AOF(默认关闭):(Append Only File)追加文件,Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件,当Redis实例宕机恢复数据时,会从这个文件中再次执行一遍命令来恢复数据

宕机恢复速度:RDB二进制文件,体积小,恢复快,但是有可能丢数据;AOF恢复慢,但是丢数据风险小,可以设置刷盘策略,everysec每秒刷盘策略

目前一般都是两种结合使用

问7: Redis的数据过期策略有哪些

答:惰性删除(/duò xìng):给key设置一个过期时间,访问该key时判断是否过期,如果过期,则删除

优点:对CPU友好,对用不到的key不用浪费时间定期检查

缺点:对内存不友好,如果key过期未使用,也不会释放内存

定期删除:定期检查一定量的key是否过期

①:SLOW(斯咯)模式:定时任务,执行频率默认为10hz,每次不超过25ms,可以通过配置文件redis.conf中的hz来修改次数

②:FAST(法斯特)模式:执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms

优点:可以通过限制删除操作执行时长和频率来减少对CPU的影响,也有效释放过期键占用的内存

缺点:难以确定删除操作执行的时长和频率

问8: Redis的数据淘汰策略有哪些

答:LRU算法(Least Recently Used):最近最少使用;用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高

LFU算法(Least Frequently Used):最少频率使用;统计每个key的访问频率,值越小淘汰优先级越高

①:noeviction(默认):不淘汰任何key,内存满时不允许写入新数据

②:volatile-ttl:对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰

③:allkeys-random:对全体key,随机进行淘汰

④:volatile-random:对设置了TTL的key,随机进行淘汰

⑤:allkeys-lru:对全体key,基于LRU算法进行淘汰

⑥:volatile-lru:对设置了TTL的key,基于LRU算法进行淘汰

⑦:allkeys-lfu:对全体key,基于LFU算法进行淘汰

⑧:volatile-lfu:对设置了TTL的key,基于LFU算法进行淘汰

问9: Redis分布式锁如何实现

答:Redis实现分布式锁主要利用Redis的setnx(赛克斯)(SET if not exists如果不存在,则SET)命令

获取锁:SET lock value NX(互斥)EX(设置超时时间)10

释放锁:DEL key

加锁,设置过期时间等操作都是基于lua脚本完成,它可以保证命令的原子性

问10: Redis实现分布式锁如何合理的控制锁的有效时长

答:在redisson(瑞第森)的分布式锁中,提供了一个WatchDog(看门狗),一个线程获取锁成功后,WatchDog会给持有锁的线程续期(默认是每隔10秒续期一次)

问11: redisson锁可以重入吗

答:可以重入,多个锁重入需要判断是否是当前线程,在redis中进行存储的时候使用的hash结构,来储存线程信息和重入的次数

问12: redisson锁能解决主从数据一致的问题吗

答:不能解决,redis思想是AP高可用思想,可以使用redisson提供的红锁来解决,但是实现复杂,性能差,运维繁琐,如果业务中必须保持数据的强一致性,可以采用zookeeper(CP强一致)实现的分布式锁

红锁(RedLock):不能只在一个redis实例上创建锁,应该在多个redis实例上创建锁(n/2+1),避免在一个redis实例上加锁

问13: Redis集群有哪些方案

答:1、主从复制(保证不了Redis的高可用):高并发读

2、哨兵模式(实现主从集群的自动故障恢复):高可用

3、Redis分片集群:海量数据存储和高并发写

问14: 什么是Redis主从同步

答:单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。一般都是一主多从,主节点负责写数据,从节点负责读数据

问15: 主从同步数据的流程

答:replication id:简称replid(r铺累特),是数据集的标记,id一致则说明是同一数据集,每一个master都有唯一的replid,slave则会继承master节点的replid

Offset:偏移量,随着记录在repl_baklog(r铺雷森拜可老歌)日志文件中的数据增多而逐渐增大,slave完成同步时也会记录当前同步的offset,如果slave的offset小于master的offset,说明slave数据落后于master,需要更新

流程一:全量同步:

1、 从节点请求主节点同步数据(replid,offset)

2、 主节点判断是否是第一次请求,是第一次就与从节点同步版本信息

3、 主节点执行bgsave,生成RDB文件后,发送给从节点去执行

4、 在RDB生成执行期间,主节点会以命令的方式记录到缓冲区(repl_baklog日志文件)

5、 把生成之后的命令日志文件发送给从节点进行同步

流程二:增量同步:

1、 从节点请求主节点同步数据,主节点判断不是第一次请求,不是第一次就获取从节点的offset值

2、 主节点从命令日志中获取offset值之后的数据,发送给从节点进行数据同步

问16: 哨兵模式

答:1、监控:Sentinel会不断检查master和slave是否按预期工作

2、自动故障恢复:如果master故障,Sentinel会将一个slave提升为master,当故障实例恢复后也以新的master为主

3、通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

哨兵选主规则:

1、 首先判断主与从节点断开时间长短,如超过指定值就排除该从节点

2、 然后判断从节点的slave-priority值,越小优先级越高

3、 如果slave-prority值一样,则判断slave节点的offset值,越大优先级越高

4、 最后是判断slave节点的运行id大小,越小优先级越高

问17: 服务状态监控

答:Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping的命令:

1、 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线

2、 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半

问18: 使用redis是单点还是集群

答:主从(1主1从)+哨兵就行。单节点不超过10G内存,如果redis内存不足则可以给不同服务分配独立的Redis主从节点

问19: redis集群脑裂

答:集群脑裂是由于主节点和从节点和sentinel处于不同的网络分区,使得sentinel没有能够心跳感知到主节点,所以通过选举的方式提升了一个从节点为主,这样就存在了两个master,这样会导致客户端还在老的主节点那里写入数据,新节点无法同步数据,当网络恢复后,sentinel会将老的主节点降为从节点,这时再从新master同步数据,就会导致数据丢失

解决方法:修改redis配置,设置最少的从节点数量min-replicas-to-write以及缩短主从数据同步的延迟时间min-replicas-max-lag,达不到要求就拒绝请求

问20: redis的分片集群的作用

答:1、集群中有多个master,每隔master保存不同数据

2、每个master都可以有多个slave节点

3、master之间通过ping监测彼此健康状态

4、客户端请求可以访问集群任意节点,最终都会被转发到正确节点

问21: redis分片集群中数据是怎么存储和读取的

答:1、redis分片集群引入了哈希槽的概念,redis集群有16384个哈希槽

2、将16384个插槽分配到不同的实例(master)

3、读写数据时根据key的有效部分计算哈希值,对16384取余(有效部分,如果key前面有大括号,大括号里的内容就是有效部分,如果没有,则以key本身作为有效部分),余数作为插槽,寻找插槽所在的实例

问22: redis是单线程的为什么还那么快

答:1、redis是纯内存操作,执行速度非常快

2、采用单线程,避免不必要的上下文切换可竞争条件,多线程还要考虑线程安全问题

3、使用I/O多路复用模型,非阻塞IO

问23: I/O多路复用模型

答:是指利用单个线程来同时监听多个Socket,并在某个Socket可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。目前的I/O多路复用都是采用的epoll模式实现,它会在通知用户进程Socket就绪的同时,把已就绪的Socket写入用户空间,不需要挨个遍历Socket来判断是否就绪,提升了性能

Redis网络模型就是使用I/O多路复用结合事件的处理器来应对多个Socket请求

1、 连接应答处理器

2、 命令回复处理器(redis6.0之后,为了提升性能,使用了多线程来处理回复事件)

命令请求处理器(redis6.0之后,将命令的转换使用了多线程,增加命令转换速度,命令执行时还是单线程)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/485986
推荐阅读
相关标签
  

闽ICP备14008679号