redis高频面试题

redis基本数据结构

redis基本数据结构

redis和数据库双写一致

双写一致性详解

redis持久化

RDB

RDB称为redis数据快照,简单来说就是将内存中的所有数据都记录到磁盘中。当redis实例故障重启时,从磁盘中读取快照文件来恢复数据。

save  #由主进程来执行rdb,会堵塞所有命令

bgsave # 由子进程来执行rdb,不影响主进程

redis内部有触发RDB的机制,在redis.conf中配置

语法:save second keyNum
示例:save 900 1 #900秒内如果有一个key被修改,则执行bgsave

RDB执行原理

bgsave会fork主进程得到子进程,子进程共享主进程的内存数据,完成fork后读取内存数据并写入rdb文件。
在这里插入图片描述
fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据然后往备份文件里读写

AOF

AOF全称为append only file(追加文件)。将redis处理的每一个写命令都记录到aof文件中,可以看做命令追加文件。

AOF配置
在这里插入图片描述因为aof是记录命令的,因此aof文件比rdb文件大得多。而且aof会记录对同一个key的多次写操作,但是只有最后一次写操作才是有效的(后面的值会覆盖前面的值)。通过执行bgrewriteaof命令,可以是aof文件执行重写功能,只会记录最新一次key操作。在这里插入图片描述总结
在这里插入图片描述

redis数据过期策略

面试题:假如redis的key过期了,该key会立即被删除吗?

Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。

惰性删除:设置该key的过期时间后,当需要该key时,会检查该key是否过期。如果该key过期了,就删除,反之,返回该key

  • 优点∶对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查

  • 缺点∶对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放

定期删除:每隔一段时间,会对一些key进行检查,删除这些key中过期的key(从一定的数据库中取出一定数量的key进行检查并删除其中过期的key)
定期删除有两种模式:

  • SLOW模式是定时任务,执行频率默认为10hz(每秒执行10次),每次不超过25ms,以通过修改配置文件redis.conf 的hz选项来调整这个次数
  • FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms

优缺点

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

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

redis的数据过期策略惰性删除 + 定期删除 组合使用

redis数据淘汰策略

数据的淘汰策略:当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。

在redis.conf的中配置数据的淘汰策略

maxmemory-policy: noeviction  # 默认

redis支持8种不同的策略来选择要删除的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算法进行淘汰

LRU算法和LFU算法

  • LRU (Least Recently Used)最近最少使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
    示例:k1在3s之前访问,k2在9s之前访问,那么被删除的k2
  • LFU (Least Frequently Used) 最少频率使用。统计每个key的访问频率,值越小淘汰优先级越高。
    示例:k1在5s内访问了4次,k2在5s内访问了9次,那么被删除的k1

数据淘汰策略使用建议

  1. 优先使用 allkeys-lru 策略。充分利用LRU算法的优势,把最近最常访问的数据留在缓存中。如果业务有明显的冷
  2. 如果业务中数据访问频率差别不大,没有明显冷热数据区分,建议使用alkeys-random,随机选择淘汰。
  3. 如果业务中有置顶的需求,可以使用volatile-lru策略,同时置顶的数据不设置过期时间,这些数据就一直不被删除,淘汰其他设置过期时间的数据。
  4. 如果业务中有短时高频访问的数据,可以使用alkeys-lfu或volatile-lfu策略。

关于数据淘汰策略其他的面试问题

1、数据库有1000万数据,Redis只能缓存20w数据,如何保证Redis中的数据都是热点数据?
使用allkeys-lru(挑选最近最少使用的数据淘汰)淘汰策略,留下来的都是经常访问的热点数据。

2、Redis的内存用完了会发生什么?
主要看数据淘汰策略是什么?如果是默认的配置( noeviction ),会直接报错。

缓存穿透、缓存击穿、缓存雪崩

缓存穿透、缓存击穿、缓存雪崩

主从同步

全量同步

在这里插入图片描述执行流程

  1. slave节点请求增量同步
  2. master节点判断replid,发现不一致,拒绝增量同步(若是slave节点第一次同步master节点,执行全量同步)
  3. master将完整内存数据生成RDB,发送RDB到slave.
  4. slave清空本地数据,加载master的RDBmaster将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
  5. slave执行接收到的命令,保持与master之间的同步

master节点判断slave节点是否是第一次同步数据?
replication_id :简称replid,数据集的标记,replid一致则是同一数据集。每一个master节点都有一个唯一的replid,slave节点会继承master节点的replid

offset:偏移量,随着记录在repl baklog中的数据增多而逐渐增大。slave节点完成同步时也会记录当前同步的offset。

slave[offset] < master[master]的情况 : slave节点的数据落后于master节点的数据,数据需要更新

slave[offset] = master[master]的情况 :slave节点的数据等于master节点的数据,与master节点的数据同步,不需要更新

slave[offset] > master[master]的情况不存在,因为slave[offset] 拷贝于master[master]

增量同步

在这里插入图片描述

redis哨兵

在这里插入图片描述
sentinel基于心跳机制监测服务状态,每隔1s向集群的每个实例发送ping命令,sentinel作用:监控、故障转移、通知。

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

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

master的选举

在这里插入图片描述

故障转移

在这里插入图片描述

Redis是单线程的为什么还这么快?

  • redis是纯内存操作,执行速度非常快
  • redis采用单线程,避免了线程上下文切换可竞争条件,而且多线程还要考虑线程安全问题
  • redis采用I/O多路复用模型,非堵塞IO

redis的性能瓶颈是网络延迟I/O多路复用模型实现了高效的网络请求。

用户空间和内核空间

在这里插入图片描述

Linux系统中一个进程使用的内存情况划分两部分:内核空间、用户空间

  • 用户空间只能执行受限的命令(Ring3),而且不能直接调用系统资源必须通过内核提供的接口来访问
  • 内核空间可以执行特权命令(Ring0),调用一切系统资源

Linux系统为了提高IO效率,会在用户空间和内核空间都加入缓冲区:

  • 写数据时,要把用户缓冲数据拷贝到内核缓冲区,然后写入设备
  • 读数据时,要从设备读取数据到内核缓冲区,然后拷贝到用户缓冲区

I/O模型

堵塞IO

在这里插入图片描述顾名思义,阻塞IO就是两个阶段都必须阻塞等待
阶段一:

  1. 用户进程尝试读取数据(比如网卡数据)
  2. 此时数据尚未到达,内核需要等待数据
  3. 此时用户进程也处于阻塞状态

阶段二:

  1. 数据到达并拷贝到内核缓冲区,代表已就绪
  2. 将内核数据拷贝到用户缓冲区
  3. 拷贝过程中,用户进程依然阻塞等待
  4. 拷贝完成,用户进程解除阻塞,处理数据

非堵塞IO

在这里插入图片描述

顾名思义,非阻塞recvfrom操作会立即返回结果而不堵塞用户进程
阶段一:

  1. 用户进程尝试读取数据(比如网卡数据)
  2. 此时数据尚未到达,内核需要等待数据
  3. 返回异常给用户进程
  4. 用户进程拿到error后,再次尝试读取
  5. 循环往复,直到数据就绪

阶段二:

  1. 将内核数据拷贝到用户缓冲区
  2. 拷贝过程中,用户进程依然阻塞等待
  3. 拷贝完成,用户进程解除阻塞,处理数据

可以看出,非堵塞IO模型中,用户进程在第一阶段是非堵塞的,但第二阶段是堵塞的。虽然是非堵塞的,但性能并没有得到提高。而且盲等机制会导致cpu空转,cpu使用率爆增。

I/O多路复用模型

IO多路复用:是利用单线程来同时监听多个socket并在某个socket可读、可写时得到通知,从而避免了无效的等待,cpu资源得到充分利用。监听socket的方式、通知的方式又有多种实现。常见的有

  • select
  • poll
  • epoll

彻底搞懂 select/poll/epoll
select/poll/epoll详解

select/poll/epoll的区别

  • select和poll只会通知用户进程有Socket就绪,但不知道是哪个socket,需要用户进程逐一确认(循环遍历)是哪个socket
  • epoll则会通知用户进程socket就绪的同时把已就绪的socket写入用户空间

在这里插入图片描述

阶段一:
1、用户进程调用select,指定要监听的Socket集合
2、内核监听对应的多个socket
3、任意一个或多个socket数据就绪则返回readable
4、此过程中用户进程阻塞
阶段二:
1、用户进程找到就绪的socket
2、依次调用recvfrom读取数据
3、内核将数据拷贝到用户空间
4、用户进程处理数据

Redis网络模型

redis通过IO多路复用来提高网络性能并支持各种不同的多路复用实现,将这些实现进行封装提供了统一的高性能事件库
在这里插入图片描述

面试题:能解释一下什么是IO多路复用

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

面试题:redis的网络模型
其中Redis的网络模型就是使用IO多路复用结合事件的处理器来应对多个Socket请求,比如,提供了连接应答处理器、命令回复处理器,命令请求处理器;
在Redis6.0之后,为了提升更好的性能,在命令回复处理器使用了多线程来处理回复事件,在命令请求处理器中,将命令的转换使用了多线程,增加命令转换速度,在命令执行的时候,依然是单线程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值