2020年我遇到的redis面试题总结

redis问题:

redis数据类型:
1、String
2、Hash
3、Set
4、sorted set
5、List
6、hyperLogLog
7、Geo
8、stream redis5.x新发布的。

redis底层实现使用了哪些数据结构?
1、动态字符串
2、链表
3、字典
4、跳跃表
5、整数集合
6、压缩表
7、对象

场景问题提问:
1、假如Redis有一亿个key,其中有十万个key有固定前缀,如何将它们快速找出来?
答题思路:
a、摸清楚数据规模,即问清楚边界

keys pattern:查找所有符合给定模式pattern的key
keys指令一次性返回所有匹配的key,键的数量过大会使服务卡顿

scan cursor [MATCH pattern] [COUNT count]
scan指令是基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程,以0作为游标开始一次新的迭代,直到命令返回游标0完成一次遍历。
不保证每次执行都返回某个给定数量的元素,支持模糊查询。一次返回的数量不可控,只能是大概率返回count参数。
缺点:返回的key可能重复。执行的时间相对keys较长。

2、如何通过redis实现分布式锁?(分布式锁是控制分布式系统或不同系统访问共享资源的一种锁的实现)
分布式锁需要解决的问题如下:
a、互斥性(任何时刻只能有一个客户端获取到锁)
b、安全性(锁只能被持有客户端删除,不能由其他客户端删除)
c、死锁(持有客户端由于某种原因宕机,未能释放持有的锁,导致其他客户端再也无法获取获得锁而一直处于等待状态,此时需要有机制避免此类事情的发生。)
d、容错(当部分节点,例如redis节点出现宕机,其他客户端仍然能获取锁,释放锁。)

setnx [KEY] [VALUE] 指令:如果key不存在,则创建并赋值。set is not exit。时间复杂度是O(1),是非常高效的。如果设置成功,返回值1,否则,返回值0。
由于setnx指令并不支持设置过期时间,所以需要使用expire指令设置过期时间。
expire [KEY] [SECOUNDS] 设置key的生存时间,当key过期时(生存时间为0)会被自动删除。
缺点:原子性得不到满足。如果执行完setnx指令,expire未能执行。则依然存在死锁的风险。
从redis 2.6.12版本我们可以使用set [KEY] [VALUE] [EX secounds] [PX millisecounds] [NX|XX]
EX secound:设置键的过期时间为secounds秒。
PX millisecounds:设置键的过期时间为millisecounds毫秒。
NX:只在键不存在时,才能进行设置操作。
XX:只在键存在时,才能进行设置操作。
set操作成功完成时,返回ok,否则返回nil。

3、大量的key同时过期的注意事项?
解决方案:集中过期,由于清除大量的key很耗时,会出现短暂的卡顿现象。在设置key的过期时间的时候,给每个key加上随机值。

4、如何使用Redis做异步队列?
使用List作为队列,rpush生产消息,使用lpop消费消息。
缺点:没有等待队列有值就直接消费。
弥补:可以通过在应用层引入Sleep机制去调用lpop重试。
如果不想使用sleep做重试?
可以使用blpop [KEY] timeount:阻塞直到队列有消息或者超时。
缺点:只能提供一个消费者消费。
能否生产一次,并让多个消费者消费呢?
可以使用pub/sub主题订阅模式。发送者pub发送消息,订阅者sub接受消息。订阅者可以订阅任意数量的频道。(subcribe mytopic; publish mytopic "hello";)
pub/sub的缺点:消息的发布是无状态的,无法保证该消息被接受到,无法确定是否在传输过程中丢失。如果订阅者在消息发布时下线,则再上线是无法接收到该消息的。
如果想要解决此类问题,那就要使用专业的消息队列kafka解决了。

5、redis有哪些持久化方案?
a、RDB(快照)持久化:保存某个时间点的全量数据快照。
缺点:内存数据的全量同步,数据会大会由于I/O严重影响性能。由于是间隔备份,可能丢失从当前至最后一次快照期间的数据。
配置:save 900 1      如果100秒之内,有1条指令,就保存快照
      save 300 10     如果300秒之内,有10条指令,就保存快照
      save 60 10000   如果60秒之内,有10000条指令,就保存快照
      save ""         禁用rdb功能。
      stop-writes-on-bgsave-error yes 当备份出错的时候,主进程就停止写入操作了。建议开启。
      rdbcompression yes 压缩备份的rdb文件。建议设置成no。因为redis本身就是cpu密集型服务器,如果再开启压缩会带来更多的cpu消耗。相比硬盘成本,CPU更值钱。
    
    RDB的创建与载入?
        rdb文件可以由两个指令:
        save阻塞Redis的服务进程,直到RDB文件被创建完成。
        save很少被使用,因为save操作是在主线程中保存快照的,由于redis是由主线
        程处理请求的,所以这种方式会阻塞所有client的请求。
        bgsave指令fork出一个子进程来创建Rdb文件,不阻塞服务器。lastsave指令能查看最后备份的时间。大家可以通过java计时器,或者quartz执行bgsave指令。(系统调用fork()创建进程,实现了copy-on-write)
        自动化触发RDB持久化的方式?
        根据redis.conf配置里的save m n 定时触发。(用的是bgsave指令的方式)
        主从复制时,主节点自动触发
        执行debug reload的时候。
        执行shutdown且没有开启AOF持久化的时候。
b、AOF(append-only-file)持久化,保存写状态。默认是关闭的。
    记录下除了查询以外的所有变更数据库状态的指令。
    以append的形式追加保存到AOF文件(增量)
    配置:
        appendonly no/yes 关闭/开启AOF持久化
        appendfilename "appendonly.aof" 设置文件名称
        appendsync everysec/always/no 配置aof文件的写入方式。alway:即时写入,everysec:每隔一秒,no:交由操作系统决定。推荐everysec的方式。
        
    日志重写解决AOF文件大小不断增大的问题,原理如下:
    调用fork()创建子进程。
    子进程把新的AOF写到一个临时文件里,不依赖原来的AOF文件。
    主进程持续将新的变动同时写到内存和原来的AOF里。
    主进程获取子进程重写AOF的完成信号,往新AOF同步增量变动。
    使用新的AOF文件替换掉旧的AOF文件。

6、redis数据的恢复?
RDB和AOF文件共存情况下的恢复流程。
redis启动的过程中,会先检查AOF是否存在,如果存在则直接加载AOF文件,而忽略掉RDB文件;如果不存在则尝试加载RDB文件。

7、RDB和AOF的优缺点?
RDB优点:全量数据快照,文件小,恢复快。
RDB缺点:无法保存最近一次快照之后的数据。
AOF优点:可读性高,适合保存增量数据,数据不易丢失。
AOF缺点:文件体积大,恢复时间长。

8、如何使用RDB-AOF混合持久化方式?
在redis4.0之后,推出了RDB-AOF混合持久化的方式,作为默认的持久化方式。
BGSAVE做镜像全量持久化,AOF做增量持久化。
         
9、为什么要使用pipeline,有什么好处?
    Pipeline和linux的管道类似。Redis基于请求/响应模型,单个请求处理需要一一应答。如果批量执行指令的时候会有大量的RTT交互时间和调用系统IO发送网络请求的。
    为了提高批量执行指令的效率,Pipeline是基于此类场景的解决方案。它允许客户端一次发送多条命令而不用等待每一条命令的结果。
    
10、是否了解redis的同步机制?如何进行redis主从同步的配置?
    主从同步原理:
    redis的正常部署中一般都是由一台master用于写的操作的,而其他若干个slave用于读操作,定期的备份也是选择单独的一台redis实例执行备份业务。
    这样可以最大程度发挥出redis的性能。为了支持数据的弱一致性,最终一致性,我们不需要保证master和slave的数据是实时同步的,但是在过了一段时间后
    它们的数据是趋于同步的。那redis可以使用主从同步,还有从从同步,第一同步时主节点做一次bgsave,并同时将后续修改操作记录到内存的缓存区,待完成后将生成
    的RDB文件全量同步到从节点。那从节点接受完成后,就将RDB的镜像加载到内存中,加载完成后再通知主节点将期间修改的操作记录及增量数据同步到slave,到某个时间点
    的存量数据同步完成后,再将增量数据同步。这样子就完成了一次主从同步。
    
    按照同步内容的多少,可以分为:全同步和增量同步
    全同步的流程:slave发送sync命令到master,master启动一个后台进程,将redis中的数据快照保存到RDB文件中,master将保存数据快照期间接收到的写命令缓存起来。
    master完成写文件操作后,将该文件发送给slave,slave接收到文件之后将文件保存到磁盘中,然后加载文件到内存中。使用新的AOF文件替换掉旧的AOF文件,master将这期间收集的
    写命令发送给slave端。
    
    增量同步过程:master接收到用户的操作指令,判断是或否需要传播到slave。增删改写操作需要传播,而查不需要。然后将该操作记录追加到aof文件,将操作传播到其他的slave。
    对齐主从库,往响应缓存写入指令。将缓冲中的数据发送给slave。
    
11、redis sentinel (sentinel译哨兵。)
    主从模式的弊端:不具备高可用性。当master挂掉之后,redis将不能对外提供写入操作。因此reids sentinel应运而生。解决主从同步master宕机后的主从切换问题。
    redis sentinel是redis官方提供的集群管理工具,其本身也是一个独立运行的进程。它能监控多个master-slave集群。master宕机之后能自动切换。只要功能有如下几点,
    监控,检查主从服务器是否运行正常;提醒,通过api向管理员或者其他应用程序报送故障。自动故障迁移,当master宕机时,主从切换,将其中一个slave升级成master。
    并让其他的slave改为复制新的master,即识别新的master做主从同步。当客户端视图连接失效的master时,集群也会返回新的master的地址。redis sentinel是一个分布式
    系统,你可以在你的架构中运行多个sentinel进程。这些进程使用流言协议,接收主服务器是否下线的信息。使用投票协议来决定是否进行自动故障迁移。以及使用哪个slave
    作为新的master。
    
    补充:流言协议Gossip。在杂乱无章中寻求一致。
    每个节点都随机地与对方通信,最终所有节点的状态达成一致。种子节点定期随机向其他节点发送节点列表,以及需要传播的消息。
    不保证信息一定会传递给所有节点,但是最终会趋于一致。

12、如何从海量数据中快速找到所需?
数据按某种规则去划分数据,分散存储在多个redis节点上。
    
    
    
    

你可能感兴趣的:(2020年我遇到的redis面试题总结)