大厂面试必问:Redis夺命11连问(建议收藏)

本文详细介绍了Redis的高性能原因,包括内存存储、底层数据结构、单线程模型和IO多路复用。还涵盖了Redis的数据类型、缓存淘汰策略、数据持久化方式如AOF日志和RDB快照。此外,讨论了Redis的高可用性、性能问题分析及解决方案,如主从切换、分布式锁实现和缓存雪崩等问题。最后,提到了Bitmap的使用场景及其在处理大数据去重和统计中的应用。
摘要由CSDN通过智能技术生成

金三银四跳槽季已经过去,还是有好多小伙伴没有找到心仪的工作。今天我来助力一把,送出这套redis面试题,助力大家通关。

1 redis为什么响应快

1.1数据保存在内存中

redis数据保存在内存中,读写操作只要访问内存,不需要磁盘IO

1.2.底层数据结构

  • redis的数据以key:value的格式存储在散列表中,时间复杂度o(1)

  • redisvalue定义了丰富的数据结构,包括动态字符串、双向链表、压缩列表、hash、跳表和整数数组,可以根据value的特性选择选择最高效的数据结构。

1.3.单线程模型

redis的网络IO和数据读写使用单线程模型,可以绑定CPU,这避免了线程上下文切换带来的开销。

「注意:redis6.0对网络请求引入了多线程模型,读写操作还是用单线程。」

redis多线程网络模型见下图:

1.4.IO多路复用

redis采用epoll网络模型,如下图:

内核会一直监听新的socket连接事件的和已建立socket连接的读写事件,把监听到的事件放到事件队列,redis使用单线程不停的处理这个事件队列。这避免了阻塞等待连接和读写事件到来。

这些事件绑定了回调函数,会调用redis的处理函数进行处理。

2 redis底层数据结构

redis有5种数据类型,包括「字符串、列表、集合、有序集合和字典」

redis底层的数据结构有6种,包括「动态字符串、双向链表、压缩列表(ziplist)、hash表、跳表(skip list)和整数数组」

redis数据类型和底层数据结构有如下对应关系:

2.1.字符串类型

底层数据结构是动态字符串。

2.2.列表

如果同时满足下面条件,就使用压缩列表,否则使用双向链表。

  • 列表中单个元素小于64字节

  • 列表中元素个数少于 512

「压缩列表」在内存中是一块儿连续的内存空间,结构如下:

「压缩列表查找时间复杂度是o(n)

2.3.集合

如果同时满足下面条件,就使用有序整数数组,否则使用hash表。

  • 集合中元素都是整数类型

  • 集合中元素个数不超过512

2.4.有序集合

如果同时满足下面2个条件,就使用压缩列表,否则使用跳表。

  • 集合中元素都小于64字节

  • 集合中元素个数小于128

「注意:有序集合还有一个HASH表用于保存集合中元素的分数,做ZSCORE操作时,查询的就是这个HASH表,所以效率很高。」

「跳表」的结构如下:

如果不加索引,查找10这个数字需要查询10次,使用了二级索引,查找10这个数字需要5次,而使用一级索引,需要查询3次。

跳表的每一层都是一个有序链表,最下面一层保存了全部数据。跳表插入、删除、查询的时间复杂度是o(logN)。跳表需要存储额外的索引节点,会增加额外的空间开销。

2.5.字典

如果同时满足下面2个条件,就使用压缩列表,否则使用hash表。

  • 字典中每个entrykey/value都小于64字节

  • 字典中元素个数小于512

3 redis缓存淘汰策略

redis总共有8种淘汰策略,如下图:

volatile-lfuallkeys-lfu策略是4.0版本新增的。

  • 「lru」是按照数据的最近最少访问原则来淘汰数据,可能存在的问题是如果大批量冷数据最近被访问了一次,就会占用大量内存空间,如果缓存满了,部分热数据就会被淘汰掉。

  • 「lfu」是按照数据的最小访问频率访问次数原则来淘汰数据,如果两个数据的访问次数相同,则把访问时间较早的数据淘汰。

4 redis数据持久化

redis持久化的方式有2种,一种是写后日志(AOF),一种是内存快照(RDB)

4.1.AOF日志

AOF日志记录了每一条收到的命令,redis故障宕机恢复时,可以加载AOF日志中的命令进行重放来进行故障恢复。AOF3种同步策略,如下图:

如果不是对丢失数据特别敏感的业务,推荐使用everysec,对主线程的阻塞少,故障后丢失数据只有1s

4.2.RDB快照

RDB快照是一个内存快照,记录了redis某一时刻的全部数据。

4.3.混合日志

redis4.0开始,AOF文件也可以保存RDB快照,AOF重写的时候redis会把AOF文件内容清空,先记录一份RDB快照,这份数据以"REDIS"开头。记录RDB内容后,AOF文件会接着记录AOF命令。故障恢复时,先加载AOF文件中RDB快照,然后回放AOF文件中后面的命令。

4.4.主从同步

redis主从同步时,主节点会先生成一份RDB快照发送给从节点,把快照之后的命令写入主从同步缓存区(replication buffer),从节点把RDB文件加载完成后,主节点把缓存区命令发送给从节点。

4.5.AOF重写

AOF日志是用记录命令的方式追加的,这样可能存在对同一个key的多条命令,这些命令是可以合并成1条的。比如对同一个key的多个set操作日志,可以合成一条。

4.6.阻塞点

AOF重写和RDB快照执行的过程中,redis都会fork一个子进程来执行操作,子进程执行过程中是不是阻塞主线程的。

「但是要注意2点:」

  • fork子进程的过程中,redis主线程会拷贝一份内存页表(记录了虚拟内存和物理内存的映射关系)给子进程,这个过程是阻塞的,redis主线程内存越大,阻塞时间越长;

  • 子进程和redis主线程共用一块儿物理内存,如果新的请求到来,必须使用copy on write的方式,拷贝要修改的数据页到新的内存空间进行修改。如下图:

注意:如果开启了内存大页,每次拷贝都需要分配2MB的内存。

5 redis高可用

下图是一个「一主二从三哨兵」的架构图:

从图我们可以看到哨兵之间、哨兵和主从节点之间、哨兵和客户端之间都建立了连接。

如果主节点挂了,哨兵集群需要完成主从切换,如下图:

下面我们依次来聊一下这4个步骤「5.1~5.4」

5.1.判断主节点下线

当一个哨兵监控到主节点下线时,就会给其他哨兵发送确认命令,其他命令会根据自己的判断回复"Y""N"

如果有n/2 + 1以上数量的哨兵都认为主节点下线了,才会判定主节点下线。这里的n是哨兵集群的数量。

n/2 + 1这个参数由quorum参数配置,比如有5个哨兵,这里一般配置成3。也可以配置成其他值。

5.2.选举新主节点

主节点被判定下线后,哨兵集群会重新选择新的主节点。

5.2.1 淘汰不稳定从节点

根据配置参数down-after-milliseconds * 10来淘汰。

「down-after-milliseconds」表示主从节点断开时间,10表示次数,如果从节点跟主节点断开时间超过down-after-milliseconds的次数达到了10次以上,从节点就被淘汰了。

5.2.2 slave-priority参数

「slave-priority」参数配置了从节点的优先级,选择从节点时哨兵会优先选择优先级高的从节点。

5.2.3 复制进度

redis有一个记录主从增量复制的缓存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值