Redis八股学习记录1Redis面试常问问题from小林coding

Redis简介

开源的内存数据结构存储,读写速度快,用于缓存,消息队列,分布式锁等场景
与Memcached的相同点:

  1. 都是内存数据库,一般都用作缓存
  2. 都有过期策略
  3. 性能高
    与memcached的不同点:
  • Redis支持的数据结构更加丰富,memcached只支持最简单的key,value结构
  • Redis支持数据的持久化,Memcached没有持久化功能
  • Redis原生支持集群模式,Memcached没有原生的集群模式
  • Redis支持发布订阅模型,Lua脚本,事务,memcached不支持

Redis数据结构

在这里插入图片描述

结构类型结构存储的值结构的读写能力
string字符串,整数或浮点数字符串操作,整数的自增自减
List链表,链表上每个都是字符串两端的push和pop操作
set集合包含字符串的无序集合字符串集合,检查字符串是否在集合中,添加,删除,获取
hash键值对的无序集合添加,删除湖片区元素
Zset键值对的有序集合字符串与浮点数的有序集合,排列由分数的大小确定

在这里插入图片描述

String底层实现

SDS(简单动态字符串)

  • 保存文本数据的同时,也能保存二进制数据
  • 获取字符串长度的时间复杂度是O(1)
  • SDS api安全,拼接字符串不会造成缓冲区溢出

List底层实现

底层由双向链表或压缩链表(小于512且元素小于64字节)实现

Hash底层实现

压缩列表(<512且所有值小于64字节)或者哈希表实现

Set底层实现

小于512整数集合,>=512哈希表

Zset

压缩列表或跳表实现

Redis线程模型

Redis单线程指的是[接受客户端请求->解析请求->进行数据读写->发送数据给客户端]是由一个线程完成的
整个Redis程序并不是单线程的,Redis程序会启动后台线程.三种线程[关闭文件,AOF刷盘,释放内存]

在这里插入图片描述
redis的reactor模型
在这里插入图片描述
Redis6.0版本之后,可以启动额外的网络IO线程,默认情况下会启动7个线程

  • Redis Server:redis的主线程,主要负责执行命令
  • bio_close_file,bio_aof_fsync,bio_lazy_fre:三个后台线程,分别处理异步关闭文件任务,AOF刷盘任务,释放内存任务
    -io_thd1-3:三个IO线程,分担Redis网络IO的压力

Redis持久化

Redis持久化有三种策略:

  • AOF日志:每执行一条写操作的命令,就把该命令以追加的形式写入到一个文件中
  • RDB快照:某一时刻的数据,以二进制方式写入磁盘
  • 混合持久化的方式:Redis4.0新增的方式,集成了AOF和RDB的优点

AOF日志的实现

Redis执行完一条写操作之后,把该命令以追加的方式写到文件中,Redis重启后,会读取该文件记录的命令,然后逐一执行的方式恢复数据
在这里插入图片描述
Redis采用先写入内存再写入AOF日志的策略原因如下

  • 避免额外的检查开销:当语法命令有问题的时候.避免错误的命令记录到AOF中
  • 不阻塞当前写操作命令的执行:因为写操作成功后,才将命令写入到AOF中

当然这样做也会带来如下的风险

  • 数据可能丢失

Redis写入AOF日志的流程如下图
Redis写入的过程
Redis提供了三种写回磁盘的策略,控制的是IO系统调用的过程,三种策略分别为Always,Everysec,No,介绍如下

  • Always:每次写操作后,都会将AOF数据写到磁盘
  • Everysec,每秒写一次磁盘
  • No,由操作系统控制写回的时机

从上到下,安全性递减,性能递增

AOF日志重写机制

AOF日志是一个文件,随着写命令增加,文件大小会增加,Redis为了避免AOF文件越来越大,提供了AOF重写机制
在这里插入图片描述
Redis的AOF重写是由后台的子进程完成的,那如何控制主进程和后台子进程的AOF一致性呢,Redis设置了一个AOF重写缓冲区,在创建子进程时使用这个缓冲区,流程如下图
在这里插入图片描述

也即是,在子进程重写时,开启AOF重写缓冲区,写入命令将会同时写入到AOF缓冲区和AOF重写缓冲区,当子进程完成重写之后,向主进程发送一条信号,主进程将AOF重写缓冲区的内容追加到新的AOF文件中,之后将这个新的AOF覆盖掉原有的AOF文件,完成AOF重写

RDB快照实现

因为AOF日志存储的是操作的命令,并不是实际的数据,因此用AOF做故障恢复时,需将日志全部执行一遍,AOF日志过多的情况下,Redis的恢复将十分缓慢
为了解决这一个问题,提出了RDB快照,RDB快照记录的时某一个瞬间内存中的内容,RDB记录同样会创建子进程,并且由于写时复制,这个时候原本的父进程依然可以执行写操作

混合持久化

RDB优势在于数据的恢复块,但是可能丢失数据
AOF数据丢失少,但是恢复慢
Redis 4.0之后混合了AOF日志和内存快照,也就是说AOF文件前半部分时RDB格式的全量数据,后半部分是AOF的增量数据
混合持久化优点

  • 混合持久化结合了 RDB 和 AOF 持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动,同时结合 AOF 的优点,有减低了大量数据丢失的风险。

混合持久化缺点

  • AOF 文件中添加了 RDB 格式的内容,使得 AOF 文件的可读性变得很差;
  • 兼容性差,如果开启混合持久化,那么此混合持久化 AOF 文件,就不能用在 Redis 4.0 之前版本了

Redis集群

Redis集群设计原因:需要高可用的Redis服务

主从复制

主从复制是Redis高可用的基础保证,实际上就是将一台Redis服务器的数据同步到多台从Redis服务器上,即一主多从的模式,且主从服务器之间采用的是读写分离的方式
在这里插入图片描述
Redis的异步主从复制是无法实现强一致性保证的

哨兵模式

使用Redis主从服务的时候,若主从服务器出现故障宕机时,需要手动进行恢复,为了解决这个问题,Redis增加了哨兵模式,哨兵模式可以监控主从服务器,并且提供主从节点之间的故障转移功能
在这里插入图片描述

切片集群模式

当Redis缓存的数据量大到一台服务器无法缓存时,就需要使用Redis切片集群,将数据分布到不同的服务器上,降低对单主节点的依赖,提高redis服务的读写性能
Redis Cluster方案采用哈希槽来处理数据和节点之间的映射关系,共16384个哈希槽
在这里插入图片描述

Redis的集群脑裂问题

情景:在一个网络波动的情况下,Redis有一个主节点A,和从节点BCD,以及哨兵E,当A与BCDE之间网络故障,但与客户端之间网络联通,这个时候客户端往A写数据,A无法同步到BCD,E发现异常并选举B作为新的主节点,在这之后网络恢复正常,并且B是新的主节点,将数据全量同步给ACD,这个时候A将清空自己的数据,并且接受B的数据,此时客户端的更新失效,产生数据丢失
解决方案:当主节点发现从节点下线或者通信超时的总量小于阈值时,禁止主节点写数据,直接把错误返回给客户端
Redis中有两个参数可以设置

  • min-slaves-to-writes x :主节点必须要有x个从节点连接,小于这个数,主节点禁止写数据
  • min-slaves-max-lag x:主从数据复制和同步的延迟不能超过x秒

Redis过期删除与内存淘汰

Redis可以对key设置过期时间,相应的机制被称为过期键值删除策略,每当对一个key设置了超时时间,Redis将会把该Key带上过期时间存储到一个过期字典中,可就是说过期字典保存了所有key的过期时间
查询一个key时,先查询是否在过期字典中

  • 不在的情况,直接读取键值
  • 存在的情况,获取key的过期时间,然后对比系统时间,若比系统时间大,则没有过期,否则判断过期

Redis使用的过期删除策略为惰性删除和定期删除

惰性删除

不主动删除Key,每次从数据库访问key时,都检测key是否过期,如果过期删除该key
优点:策略对CPU时间友好
缺点:浪费内存空间

定期删除

每隔一段时间从数据库取出一定数量的key进行检查,删除其中过期的key
在这里插入图片描述
优点:限制删除操作时长和频率,减少删除操作对CPU的影响,同时尽量节约空间
缺点:难以确定删除时长和频率,执行太过频繁对CPU不友好

Redis持久化时,对过期的键如何处理

Redis持久化时,文件有两种表现形RDB和AOF,过期键在这两种格式下的呈现状态如下
RDB分为两个阶段:

  • RDB文件生成阶段:内存状态持久化生成RDB文件时,对Key进行过期检查,过期的key将不被保存到RDB文件中
  • RDB文件加载阶段:RDB加载阶段,看服务器是主服务器还是从服务器,主服务器的情况下:载入RDB时,过期检查,如果过期不会被加载到数据库中,从服务器的情况下:不论是否过期都加载

AOF分为两个阶段,写入阶段和加载阶段:

  • 写入阶段:当Redis以AOF模式进行持久化时,若数据库的某个过期键未被删除,那么AOF文件会保留此过期键,当过期键被删除之后,Redis会向AOF文件追加一条DEL命令显式删除该键值
  • AOF重写阶段:执行重写时,进行过期检查,已过期的键不会保存到重写后的AOF文件中

Redis主从模式中,对过期键如何处理

Redis运行在主从模式下时,从库不会进行过期扫描,从库对过期的处理是被动的,也就是依赖主库的控制,主库的Key在到期时,会在AOF文件里增加一条DEL指令,同步到所有的从库

Redis处理内存满了的问题

Redis的运行内存达到了某个阈值,就会触发内存淘汰机制,阈值是设置的最大运行内存,淘汰策略有八种,主要是依照LRU和LFU策略设计的

Redis缓存设计

Redis使用典型场景
在这里插入图片描述

缓存雪崩问题

Redis数据过期之后,用户访问的数据如果不在缓存里,业务系统需要重新生成缓存,这时候需要访问数据库,并将数据库更新到Redis后,以后的请求可以直接命中缓存
缓存雪崩问题是指:大量的缓存在同一时间过期时,若有大量的用户请求,都无法在Redis中处理,所有的请求全部访问数据库,导致数据库的压力骤增,严重的导致数据库宕机,从而导致一系列的连锁反应,造成整个系统崩溃,这就是缓存雪崩问题
缓存雪崩问题的解决方案:1.将缓存失效的时间随机打散2.设置缓存不过期

缓存击穿问题

缓存击穿问题是指,业务有几个数据会被频繁的访问,如果缓存中的某个热点数据过期了,此时大量的请求访问了该热点数据,转而直接访问数据库,数据库很容易高并发的请求冲垮,这就是缓存击穿问题
在这里插入图片描述
缓存击穿避免方式:

  1. 互斥锁,设置一段时间仅有一个业务线程请求访问缓存
  2. 不给热点数据设置过期时间

缓存穿透问题

发生缓存雪崩或者击穿时,数据库中依然保存了应用要访问的数据,一旦缓存恢复相对应的数据,就可以减轻数据库的压力,当用户访问的数据,既不在缓存中,也不在数据库中,导致请求访问缓存时,发现缓存缺失,转而访问数据库,而数据库中也没有要访问的数据,没办法构建缓存数据,当有大量的请求到来时,数据库压力剧增,这就是缓存穿透问题
缓存穿透发生有两种情况

  • 业务误操作:缓存中的数据和数据库中的数据都被误删除了,导致缓存和数据库中都没有操作
  • 黑客恶意攻击:大量访问某些不存在数据的业务

缓存穿透的应对措施三种

  • 非法请求的限制,在api的入口处判断请求参数是否合理,判断出恶意请求需要直接返回错误,避免进一步访问缓存和数据库
  • 设置空值或者默认值 :当线上业务发现缓存穿透时,缓存这个空值
  • 设置布隆过滤器判断数据是否存在,避免查询数据库来判断数据是否存在

如何设计缓存策略,可以动态缓存热点数据

将一部分热点数据缓存起来,策略的思路是,通过数据的最新访问时间来做排名,过滤掉不常访问的数据,留下经常访问的数据

Redis常见的缓存更新策略

三种常见的缓存更新策略

  • Cache Aside:旁路缓存策略
  • Read/Write Through(读穿/写穿)策略
  • Write Back(写回策略)
    在实际开发中,使用的是Cache Aside,另外两种策略应用不了

Cache Aside

在这里插入图片描述
写策略的步骤:

  • 先更新数据库中的内容,再删除缓存中的数据

读策略的步骤:

  • 如果命中数据,那么直接返回数据
  • 如果数据没命中缓存,那么从数据库中读取数据,然后将数据写到缓存中,并返回给用户

Redis实战

Redis如何实现延迟队列

延迟队列类似于定时器,那么Redis用ZSet加上轮询队列,处理回调即可完成延迟队列的实现

Redis的大key如何处理

大key是指Redis的key对应的value很大(元素多或者单个元素占用的空间很大)

大Key的影响

  • 客户端超时阻塞.Redis是单线程处理,因此单个的大Key操作会比较耗时,那么就会阻塞Redis,从客户端来看,就是很久都没有响应
  • 引发网络阻塞.每次大key产生的流量比较大
  • 阻塞工作线程,如果删除大key时,会阻塞工作线程,导致没法处理后续的命令
  • 内存分布不均
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值