Redis面试题总结分享-程序员宅基地

技术标签: java  数据库  redis  

Redis经典面试题总结分享

一、常见面试题分享

1.Redis优点和缺点

优点:

  1. 本质上是一个 Key-Value 类型的内存数据库
  2. 整个数据库加载在内存当中进行操作,定期通过异步操作把数据库数据 flush 到硬盘上进行保存
  3. 因为是纯内存操作,Redis 的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的Key-Value DB
  4. 支持保存多种数据结构(string,list,set,hash,sortedset),单个 value 的最大限制是 1GB,
  5. Redis也可以对存入的 Key-Value 设置 expire 时间

缺点:

  1. Redis 的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写

2.Redis有哪些数据删除策略?

简介:

Redis中可以对数据设置数据的有效时间,数据的有效时间到了以后,就需要将数据从内存中删除掉。而删除的时候就需要按照指定的规则进行删除,这种删除规则就被称之为数据的删除策略

定时删除

  • 概述:在设置某个key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作。
  • 优点:定时删除对内存是最友好的,能够保存内存的key一旦过期就能立即从内存中删除。
  • 缺点:对CPU最不友好,在过期键比较多的时候,删除过期键会占用一部分CPU时间,对服务器的
    响应时间和吞吐量造成影响。

惰性删除

  • 概述:设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。
  • 优点:对CPU友好,我们只会在使用该键时才会进行过期检查,对于很多用不到的key不用浪费时
    间进行过期检查
  • 缺点:对内存不友好,如果一个键已经过期,但是一直没有使用,那么该键就会一直存在内存中,
    如果数据库中有很多这种使用不到的过期键,这些键便永远不会被删除,内存永远不会释放。

定期删除

  • 概述:每隔一段时间,我们就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取
    出一定数量的随机键进行检查,并删除其中的过期键)。
  • 优点:可以通过限制删除操作执行的时长和频率来减少删除操作对 CPU 的影响。另外定期删除,
    也能有效释放过期键占用的内存。
  • 缺点:难以确定删除操作执行的时长和频率。如果执行的太频繁,定期删除策略变得和定时删除策略一样,对CPU不友好。如果执行的太少,那又和惰性删除一样了,过期键占用的内存不会及时得
    到释放。

注意
另外最重要的是,在获取某个键时,如果某个键的过期时间已经到了,但是还没执行定期删除,那么就会返回这个键的值,这是业务不能忍受的错误。

Redis的过期删除策略:惰性删除 + 定期删除两种策略进行配合使用定期删除函数的运行频率

在Redis2.6版本中,规定每秒运行10次,大概100ms运行一次。在Redis2.8版本后,可以通过修改配置文件redis.conf 的 hz 选项来调整这个次数。

3.Redis中有哪些数据淘汰策略?

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

noeviction # 不删除任何数据,内存不足直接报错(默认策略)
volatile-lru # 挑选最近最久使用的数据淘汰(举例:key1是在3s之前访问的, key2是在9s之前访问的,删除的就是key2)
volatile-lfu # 挑选最近最少使用数据淘汰 (举例:key1最近5s访问了4, key2最近5s访问了9次, 删除的就是key1)
volatile-ttl # 挑选将要过期的数据淘汰
volatile-random # 任意选择数据淘汰
allkeys-lru # 挑选最近最少使用的数据淘汰
allkeys-lfu # 挑选最近使用次数最少的数据淘汰
allkeys-random # 任意选择数据淘汰,相当于随机

注意:

  1. 不带allkeys字样的淘汰策略是随机从Redis中选择指定的数量的key然后按照对应的淘汰策略进行删除,带allkeys是对所有的key按照对应的淘汰策略进行删除。

4.Redis中数据库默认是多少个db即作用?

  1. Redis默认支持16个数据库,可以通过配置databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用select命令更换数据库。
  2. Redis支持多个数据库,并且每个数据库是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。

5.缓存穿透、缓存击穿、缓存雪崩解决方案?

缓存穿透:

概述:指查询一个一定不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。

解决方案

  1. 查询返回的数据为空,仍把这个空结果进行缓存,但过期时间会比较短
  2. 布隆过滤器:将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对DB的查询

缓存击穿:

概述:对于设置了过期时间的key,缓存在某个时间点过期的时候,恰好这时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把 DB 压垮。
解决方案

  1. 使用互斥锁:当缓存失效时,不立即去load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db的操作并回设缓存,否则重试get缓存的方法

缓存雪崩:

概述:设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB 瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多key,击穿是某一个key缓存。
解决方案
将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件

6.Redis数据持久化有哪些方式?各自有什么优缺点?

在Redis中提供了两种数据持久化的方式:RDB 和 AOF

RDB

定期更新,定期将Redis中的数据生成的快照同步到磁盘等介质上,磁盘上保存的就是Redis的内存快照

save [seconds] [changes]  
save  60 100
save  600 500

优点

  1. 对性能影响最小。如前文所述,Redis在保存RDB快照时会fork出子进程进行,几乎不影响Redis处理客户端请求的效率。
  2. 每次快照会生成一个完整的数据快照文件,所以可以辅以其他手段保存多个时间点的快照(例如把每天0点的快照备份至其他存储媒介中),作为非常可靠的灾难恢复手段。
  3. 使用RDB文件进行数据恢复比使用AOF要快很多。

缺点

  1. 快照是定期生成的,所以在Redis crash时或多或少会丢失一部分数据
  2. 如果数据集非常大且CPU不够强(比如单核CPU),Redis在fork子进程时可能会消耗相对较长的时间,影响Redis对外提供服务的能力

AOF

采用AOF持久方式时,Redis会把每一个写请求都记录在一个日志文件里。在Redis重启时,会把AOF文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新。
AOF默认是关闭的,如要开启,进行如下配置:

  appendonly  yes 

AOF提供了三种fsync配置:always/everysec/no,通过配置项[appendfsync]指定:

  1. appendfsync no:不进行fsync,将flush文件的时机交给OS决定,速度最快
  2. appendfsync always:每写入一条日志就进行一次fsync操作,数据安全性最高,但速度最慢
  3. appendfsync everysec:折中的做法,交由后台线程每秒fsync一次

优点
4. 最安全,在启用appendfsync为always时,任何已写入的数据都不会丢失,使用在启用appendfsync everysec也至多只会丢失1秒的数据
5. AOF文件在发生断电等问题时也不会损坏,即使出现了某条日志只写入了一半的情况,也可以使用redis-check-aof工具轻松修复
6. AOF文件易读,可修改,在进行某些错误的数据清除操作后,只要AOF文件没有rewrite,就可以把AOF文件备份出来,把错误的命令删除,然后恢复数据。

缺点

  1. AOF文件通常比RDB文件更大
  2. 性能消耗比RDB高
  3. 数据恢复速度比RDB慢

Redis的数据持久化工作本身就会带来延迟,需要根据数据的安全级别和性能要求制定合理的持久化策略:

  • AOF + fsync always的设置虽然能够绝对确保数据安全,但每个操作都会触发一次fsync,会对Redis的性能有比较明显的影响
  • AOF + fsync every second是比较好的折中方案,每秒fsync一次
  • AOF + fsync never会提供AOF持久化方案下的最优性能

使用RDB持久化通常会提供比使用AOF更高的性能,但需要注意RDB的策略配置

7.Redis都存在哪些集群方案?

主从复制

  1. 保证高可用性
  2. 实现故障转移需要手动实现
  3. 无法实现海量数据存储
    哨兵模式
  4. 保证高可用性
  5. 可以实现自动化的故障转移
  6. 无法实现海量数据存储
    Redis分片集群
  7. 保证高可用性
  8. 可以实现自动化的故障转移
  9. 可以实现海量数据存储

8.Redis哈希槽的概念?

Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。

9.谈谈你对Redis中事务的理解?

事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
Redis中的事务:Redis事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
总结说:Redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。Reids中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚

10.为什么Redis不支持事务回滚?

多数事务失败是由语法错误或者数据结构类型错误导致的,语法错误说明在命令入队前就进行检测的,而类型错误是在执行时检测的,Redis为提升性能而采用这种简单的事务,这是不同于关系型数据库的,特别要注意区分。Redis之所以保持这样简易的事务,完全是为了保证高并发下的核心问题——性能

11.Redis事务相关的命令有哪几个?

  1. MULTI:用来组装一个事务
  2. EXEC:执行一个事物
  3. DISCARD:取消一个事务
  4. WATCH:用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行
  5. UNWATCH:取消 WATCH 命令对所有key的监视

12.Redis是单线的,但是为什么还那么快?

  1. 完全基于内存的
  2. 采用单线程,避免不必要的上下文切换可竞争条件
  3. 数据简单,数据操作也相对简单
  4. 使用多路I/O复用模型,非阻塞IO

13.Redis怎么实现分布式锁思路?

Redis实现分布式锁主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在,则 SET)的简写。

127.0.0.1:6379> setnx lock value1 #在键lock不存在的情况下,将键key的值设置为value1
(integer) 1
127.0.0.1:6379> setnx lock value2 #试图覆盖lock的值,返回0表示失败
(integer) 0
127.0.0.1:6379> get lock #获取lock的值,验证没有被覆盖
"value1"
127.0.0.1:6379> del lock #删除lock的值,删除成功
(integer) 1
127.0.0.1:6379> setnx lock value2 #再使用setnx命令设置,返回0表示成功
(integer) 1
127.0.0.1:6379> get lock #获取lock的值,验证设置成功
"value2"

上面这几个命令就是最基本的用来完成分布式锁的命令。

加锁:使用 setnx key value 命令,如果key不存在,设置value(加锁成功)。如果已经存在lock(也就是有客户端持有锁了),则设置失败(加锁失败)。

解锁:使用 del 命令,通过删除键值释放锁。释放锁之后,其他客户端可以通过 setnx 命令进行加锁。

14.Redis实现分布式锁如何防止死锁现象?

产生死锁的原因:如果一个客户端持有锁的期间突然崩溃了,就会导致无法解锁,最后导致出现死锁的现象。
所以要有个超时的机制,在设置key的值时,需要加上有效时间,如果有效时间过期了,就会自动失效,就不会出现死锁。

15.Redis实现分布式锁如何合理的控制锁的有效时长?

有效时间设置过长,假如我的业务操作比有效时间长?我的业务代码还没执行完就自动给我解锁了,不就完蛋了吗。
解决方案

  1. 自己去把握,预估一下业务代码需要执行的时间,然后设置有效期时间比执行时间长
    一些,保证不会因为自动解锁影响到客户端业务代码的执行。
  2. 给锁续期。锁续期实现思路:当加锁成功后,同时开启守护线程,默认有效期是用户所设置的,然后每隔10秒就会给锁续期到用户所设置的有效期,只要持有锁的客户端没有宕机,就能保证一直持有锁,直到业务代码执行完毕由客户端自己解锁,如果宕机了自然就在有效期失效后自动解锁。

16. 为什么要在多个实例上加锁?

本质上是为了【容错】, 部分实例异常宕机,剩余的实例加锁成功,整个锁服务依旧可用。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41805567/article/details/129558942

智能推荐

hdu 1229 还是A+B(水)-程序员宅基地

文章浏览阅读122次。还是A+BTime Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24568Accepted Submission(s): 11729Problem Description读入两个小于10000的正整数A和B,计算A+B。...

http客户端Feign——日志配置_feign 日志设置-程序员宅基地

文章浏览阅读419次。HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息。FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。BASIC:仅记录请求的方法,URL以及响应状态码和执行时间。NONE:不记录任何日志信息,这是默认值。配置Feign日志有两种方式;方式二:java代码实现。注解中声明则代表某服务。方式一:配置文件方式。_feign 日志设置

[转载]将容器管理的持久性 Bean 用于面向服务的体系结构-程序员宅基地

文章浏览阅读155次。将容器管理的持久性 Bean 用于面向服务的体系结构本文将介绍如何使用 IBM WebSphere Process Server 对容器管理的持久性 (CMP) Bean的连接和持久性逻辑加以控制,使其可以存储在非关系数据库..._javax.ejb.objectnotfoundexception: no such entity!

基础java练习题(递归)_java 递归例题-程序员宅基地

文章浏览阅读1.5k次。基础java练习题一、递归实现跳台阶从第一级跳到第n级,有多少种跳法一次可跳一级,也可跳两级。还能跳三级import java.math.BigDecimal;import java.util.Scanner;public class Main{ public static void main(String[]args){ Scanner reader=new Scanner(System.in); while(reader.hasNext()){ _java 递归例题

面向对象程序设计(荣誉)实验一 String_对存储在string数组内的所有以字符‘a’开始并以字符‘e’结尾的单词做加密处理。-程序员宅基地

文章浏览阅读1.5k次,点赞6次,收藏6次。目录1.串应用- 计算一个串的最长的真前后缀题目描述输入输出样例输入样例输出题解2.字符串替换(string)题目描述输入输出样例输入样例输出题解3.可重叠子串 (Ver. I)题目描述输入输出样例输入样例输出题解4.字符串操作(string)题目描述输入输出样例输入样例输出题解1.串应用- 计算一个串的最长的真前后缀题目描述给定一个串,如ABCDAB,则ABCDAB的真前缀有:{ A, AB,ABC, ABCD, ABCDA }ABCDAB的真后缀有:{ B, AB,DAB, CDAB, BCDAB_对存储在string数组内的所有以字符‘a’开始并以字符‘e’结尾的单词做加密处理。

算法设计与问题求解/西安交通大学本科课程MOOC/C_算法设计与问题求解西安交通大学-程序员宅基地

文章浏览阅读68次。西安交通大学/算法设计与问题求解/树与二叉树/MOOC_算法设计与问题求解西安交通大学

随便推点

[Vue warn]: Computed property “totalPrice“ was assigned to but it has no setter._computed property "totalprice" was assigned to but-程序员宅基地

文章浏览阅读1.6k次。问题:在Vue项目中出现如下错误提示:[Vue warn]: Computed property "totalPrice" was assigned to but it has no setter. (found in <Anonymous>)代码:<input v-model="totalPrice"/>原因:v-model命令,因Vue 的双向数据绑定原理 , 会自动操作 totalPrice, 对其进行set 操作而 totalPrice 作为计..._computed property "totalprice" was assigned to but it has no setter.

basic1003-我要通过!13行搞定:也许是全网最奇葩解法_basic 1003 case 1-程序员宅基地

文章浏览阅读60次。十分暴力而简洁的解决方式:读取P和T的位置并自动生成唯一正确答案,将题给测点与之对比,不一样就给我爬!_basic 1003 case 1

服务器浏览war文件,详解将Web项目War包部署到Tomcat服务器基本步骤-程序员宅基地

文章浏览阅读422次。原标题:详解将Web项目War包部署到Tomcat服务器基本步骤详解将Web项目War包部署到Tomcat服务器基本步骤1 War包War包一般是在进行Web开发时,通常是一个网站Project下的所有源码的集合,里面包含前台HTML/CSS/JS的代码,也包含Java的代码。当开发人员在自己的开发机器上调试所有代码并通过后,为了交给测试人员测试和未来进行产品发布,都需要将开发人员的源码打包成Wa..._/opt/bosssoft/war/medical-web.war/web-inf/web.xml of module medical-web.war.

python组成三位无重复数字_python组合无重复三位数的实例-程序员宅基地

文章浏览阅读3k次,点赞3次,收藏13次。# -*- coding: utf-8 -*-# 简述:这里有四个数字,分别是:1、2、3、4#提问:能组成多少个互不相同且无重复数字的三位数?各是多少?def f(n):list=[]count=0for i in range(1,n+1):for j in range(1, n+1):for k in range(1, n+1):if i!=j and j!=k and i!=k:list.a..._python求从0到9任意组合成三位数数字不能重复并输出

ElementUl中的el-table怎样吧0和1改变为男和女_elementui table 性别-程序员宅基地

文章浏览阅读1k次,点赞3次,收藏2次。<el-table-column prop="studentSex" label="性别" :formatter="sex"></el-table-column>然后就在vue的methods中写方法就OK了methods: { sex(row,index){ if(row.studentSex == 1){ return '男'; }else{ return '女'; }..._elementui table 性别

java文件操作之移动文件到指定的目录_java中怎么将pro.txt移动到design_mode_code根目录下-程序员宅基地

文章浏览阅读1.1k次。java文件操作之移动文件到指定的目录_java中怎么将pro.txt移动到design_mode_code根目录下

推荐文章

热门文章

相关标签