redis面试题

175 阅读12分钟

1、什么是redis

redis是一种nosql数据库,他的数据是保存在内存中,以键值对的形式存储数据,同时redis可以定时把内存数据同步到磁盘,即可以数据持久化,并且他比memcached支持更多的数据结构(string、list、列表[队列和栈],set[集合],sorted,set[有序集合]hash[hash表]))

2、为什么要使用redis

当我们做了一个项目,比方说个人博客,我们把这个项目发布到自己的服务器,一般来说我们做这个项目没有商用,所以访问量会很小,这个时候,我们不使用redis也可以,我们知道mysql是在外存中的,读取需要一点时间,访问量小的时候,这些时间我们可以忽略不计,但是,当我们做了一个大型的商用项目,例如淘宝,那么访问量就会几何数上升,并发量会十分的大,这时候如果我们还是用mysql,那么大量的访问会使服务器的处理速度会非常的慢,所以这时候我们就要使用redis,redis是在内存上面,我们知道内存读取数据非常的快,当大量的用户去访问某个数据的时候,我们把数据存放在redis中,这样既缓解了mysql的请求压力,又服务器的正常运行

3、什么是redis雪崩

当大量的redis失效的时候,大量的访问直接打在我们的数据库上面,于是导致服务器访问变慢甚至宕机 解决方法: 设置redis永远不会过期 给每一个redis设置随机的过期时间

4、什么是redis缓存击穿

当出现一个热点数据,例如胡歌结婚了,这就是一个热点数据,当有大量的访问同时访问一个数据,然后这个热点数据在某个时段过期了,那么大量的请求就会打在我们的数据库上面,便会造成服务器的宕机; 解决方法:

当redis热点数据失效时,我们把全部的访问量锁住,只通过一个访问,让他去数据库查询,查询到数据之后,redis上便会存在锁需要的数据,然后这个时候在放行全部的请求,这样全部的请求就会打在redis上面,不会大道我们的数据库了

5、什么是redis穿透

当我们访问的时候是需要携带参数的,比如携带id=1这样的参数,访问后就在内存里面存储查询到的数据,但是有些人会发起一些恶意请求,比如说id=-10000,id=sdfaidfiuah这样的,那么这些是不存在的,当这样的请求一旦多起来,那么数据库就很有可能会崩; 解决方法:

有很多方法可以有效解决缓存穿透文图,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据就会被这个bitMap拦截掉,从而避免了对底层存储系统的查询压力;

另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

6、Redis常见的数据结构

基础:

String:字符串,最基本的类型 List:列表 Hash:哈希 Set:无序集合 Zset:有序集合

高级: HyperLogLog:通常用于基数统计(例如,网站访客统计)

BitMap:位图

Stream:主要用于消息队列,类似与kafka,可以认为是pub/sub的改进版。提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户的访问位置,还能保证消息不丢失

Geo:redis3.2版本的新特性,可以将用户给定的地理位置信息储存起来,并对这些信息进行操作:获取2个位置的距离、根据给定地理位置坐标获取指定范围内的地理位置集合

7、Redis在项目中的使用场景

(1)计数器:可以对string进行自增自减运算,从而实现计数器功能,Redis这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量

(2)缓存:将热点数据放到内存中,设置内存的最大使用量及淘汰策略来保证缓存的命中率

(3)会话缓存:可以使用Redis来统一多台应用服务器的会话信息,当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性

(3)全页缓存(fpc):除基本的会话token之外,redis还提供了很简便的FPC平台。以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。

(4)查找表:例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存类似,也是利用了 Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效,因为缓存不作为可靠的数据来源

(5)消息队列(发布/订阅功能):List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过最好使用 Kafka、RabbitMQ 等消息中间件。

(6)分布式锁实现:在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。

8、Redis是单线程还是多线程的?

reids在4.0之前是完全单线程的 redis4.0时,redis引入了多线程,但是额外的线程只是用于后台处理,例如:删除对象,核心流程还是完全单线程的,(核心流程指的是redis正常处理客户端请求的流程,通常包括:接收命令、解析命令、执行命令、返回结果) redis 6.0中,多线程主要用于网络i/o阶段,也就是接收命令和写回结果阶段,而在执行命令阶段,还是单线程串行执行,

9、为什么redis是单线程?

1、redis是基本内存的操作 2、redis使用了i/o多路复用模型 3、单线程可以避免不必要的上下文切换和竞争条件,减少了性能消耗 4、在redis6.0之前,redis的核心操作是单线程的,因为redis是完全基于内存操作的,通常情况下CPU不会是redis的瓶颈,redis的瓶颈最有可能是机器内存的大小或者网络带宽。

redis的持久化机制是什么?各自的优缺点?

redis持久化机制 1、RDB(默认)是redis默认的持久化方式,按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期

image.png 优点: 只有一个文件dump.rdb,方便持久化

容灾性好,一个文件可以保存到安全的磁盘

性能最大化,fork子线程来完成写操作,让主线程继续处理命令,所以是IO最大化,使用单独子进程来进行持久化,主线程不会进行任何IO操作,保证了redis的高性能

相对于数据集大时,比AOF的启动效率更高 缺点: 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)

AOF(Append-only file)持久化方式:是指所有的命令行记录以 redis 命令请求协议的格式完全持久化存储)保存为aof文件。

2、AOF AOF持久化(即Append Only File持久化),则是将Redis执行的每次写命令记录日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。当两种方式同时开启时,数据恢复Redis会优先选择AOF

image.png 优点: 数据安全,aof持久化可以配置appendfsync属性,有always,每进行一次命令操作就记录到aof文件中一次

通过append模式写文件,即使中途服务器宕机,可以通过redis-check-aof工具解决数据一致性问题

Aof机制的rewirte模式,AOF文件没被rewrite之前,可以删除其中的某些命令

缺点: AOF文件比RDB文件大,且恢复速度慢

数据极大的时候,比rdb启动效率低

3、两者对比 (1)AOF文件比RDB更新频率高,优先使用AOF还原数据 (2)AOF比RDB更安全也更大 (3)RDB性能比AOF好 (4)如果两个都配优选加载AOF

10、Redis的过期键的删除策略

众所周知,Redis是非关系型数据库,我们可以设置key的过期时间,redis的过期策略就是说说当redis缓存的key过期了,redis应该怎么处理

过期策略有以下三种: 1、主动过期:每一个key都要设置过期时间,时间一到就马上清除,对内存很友好,但是会占用大量的cpu资源去处理过期数据,从而影响缓存的响应时间和吞吐量

2、惰性过期:只有某个访问用到这个key的时候,才会判断这个key是否过期,过期就清除,没过期便不会 ,这样节省了很多的cpu资源,但是对内存不友好,有可能出现一堆没有过期的key存在内存

3、定期过期:每过一段时间,会扫描一定数量的key,清除过期的,这个是一个这中方案

11、Redis key的过期时间和永久有效分别怎么设置

EXPIRE和PERSIST

12、Redis的内存用完了会发什么

如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回),或者你可以配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内存

13、什么是RDB

RDB:把目前redis内存中数据,生成一个快照(RDB文件),保存在硬盘中,如果发生事故,redis可以通过RDB文件,进行文件读取,并将数据重新载入内存中,它是一种全量备份的机制。

RDB的触发条件:

手动触发:
  save:执行该指令后,主线程执行rdbSave函数,服务器进程阻塞,即不能处理任何其他请求
  bgSave(background save):本质上这个命令和save差不多,区别在于命令会fork一个一个子线程,去执行rdbSave函数,因此主线程还是可以执行新请求的

自动触发:配置文件中写入save m n ,代表当m秒内发生n次变化时,会自动执行bgsave

14、什么是AOF

AOF:记录之后所有对Redis数据进行修改的操作,如果发生事故,redis可以通过AOF文件,将文件中的数据修改命令全部执行一遍,以此恢复数据。

AOF的重写与恢复:文件重写策略,创建一个新的AOF文件,以替代原有的冗余的AOF文件

AOF的触发条件 手动触发:输入指令bgrewriteaof

自动触发:配置文件中设置appendonly yes开启
 自动触发的写入策略:
     (1)Always:即同步写回,在每个写命令执行完成后,直接将命令 落入磁盘文件(数据基本保证可靠性,但是影响Redis的性能)
     (2)Everysec:即每秒写回,对于每一个命令执行完成后,该命令被写入文件的内容缓存区,每过1秒,redis会把该缓存区命令写到磁盘的AOF文件中
     (3)NO,这个No不是不执行AOF,而是将操作命令全部只写到Redis缓存区,至于在何时将缓存数据落盘,交给操作系统决定
     Redis默认是Everysec

15、主从复制

(1)当主库从库上线后,他们不着急直接复制过程,首先需要进行握手,进行信息验证 image.png (2)当握手完成后,从库需要发送向主库发送PSYN命令,即同步命令,开启数据同步过程,并发送主库ID,复制的进度偏移量offset image.png (3)主库会根据从库发送的信息,进行逻辑判断,并告诉从库,是进行全量复制/断线后重复制 image.png 全量复制:初次复制后的同步

主库执行BGSAVE,生成对应的RDB文件,同时开辟缓冲区,记录在RDB文件实行过程中,收到的新数据命令;

RDB文件产生后,主库发给从库,从库通过RDB恢复数据 (4)命令传播阶段 主库状态被修改了(如增、改原始数据),为了使得从库和主库数据状态一致,主库将会把数据变更命令发给从库,从库收到后执行命令。