Redis经典面试题总结
1. 什么是Redis?它主要用来什么的?
Redis,英文全称是Remote Dictionary Server(远程字典服务),是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
与MySQL数据库不同的是,Redis的数据是存在内存中的。它的读写速度非常快,每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存,另外,Redis也经常用来做分布式锁。除此之外,Redis支持事务、持久化、LUA 脚本、LRU 驱动事件、多种集群方案。
2.Redis的基本数据结构类型
Redis有以下这五种基本类型:
- String(字符串)
- Hash(哈希)
- List(列表)
- Set(集合)
- zset(有序集合)
3. Redis为什么这么快?
3.1 基于内存存储实现
Redis基于内存存储实现的数据库,相对于数据存在磁盘的MySQL数据库,省去磁盘I/O的消耗。
3.2 合理的数据编码
譬如:String类型如果存储数字的话,是用int类型的编码
3.3 合理的线程模型
- I/O 多路复用: IO多路复用其实就是一种同步IO模型,它实现了一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;而没有文件句柄就绪时,就会阻塞应用程序,交出cpu。
- 单线程模型: Redis是单线程模型的,而单线程避免了CPU不必要的上下文切换和竞争锁的消耗。也正因为是单线程,如果某个命令执行过长(如hgetall命令),会造成阻塞。Redis是面向快速执行场景的数据库。所以要慎用如smembers和lrange、hgetall等命令。
IO多路复用程序(这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程)会监听多个Socket,将Socket产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
Redis客户端对服务端的每次调用都经历了发送命令,执行命令,返回结果三个过程。其中执行命令阶段,由于Redis是单线程来处理命令的,所有每一条到达服务端的命令不会立刻执行,所有的命令都会进入一个队列中,然后逐个被执行。并且多个客户端发送的命令的执行顺序是不确定的。但是可以确定的是不会有两条命令被同时执行,不会产生并发问题,这就是Redis的单线程基本模型。
4. 什么是缓存击穿、缓存穿透、缓存雪崩?
4.1 缓存击穿问题
缓存击穿: 指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。缓存击穿和缓存雪崩区别在于击穿针对某一热点key缓存,雪崩则是很多key。
如何避免缓存击穿问题,解决方案就有两种:
- 使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(edis的setnx()方法或者redisTemplate的setIfAbsent()方法)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
- “永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。
4.2 缓存穿透问题
缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。
如何避免缓存穿透呢? 一般有三种方法:
- 如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。
- 如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。
- 使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。
4.2 缓存雪奔问题
缓存雪奔: 指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。
如何避免缓存雪崩问题:
- 缓存雪奔一般是由于大量数据同时过期造成的。
- Redis 故障宕机也可能引起缓存雪奔,这就需要构造Redis高可用集群。
5. Redis 过期策略和内存淘汰策略
5.1 Redis的过期策略
- 定时过期 每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即对key进行清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
- 惰性过期 只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
- 定期过期 每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
Redis中同时使用了惰性过期和定期过期两种过期策略。
5.2 Redis 内存淘汰策略(逐出算法)
Redis使用内存存储数据,在执行每一个命令前,会调用freeMemoryIfNeeded()检测内存是否充足。如果内存不满足新加入数据的最低存储要求,redis要临时删除一些数据为当前指令清理存储空间。
5.2.1 常用的逐出算法:
5.2.2 影响数据逐出的相关配置
- maxmemory (最大可使用内存): 占用物理内存的比例,默认值为0,表示不限制。生产环境中根据需求设定,通常设置在50%以上。
- maxmemory-samples ( 每次选取待删除数据的个数) : 选取数据时并不会全库扫描,导致严重的性能消耗,降低读写性能。因此采用随机获取数据的方式作为待检测删除数据。
- maxmemory-policy ( 删除策略) : 达到最大内存后的,对被挑选出来的数据进行删除的策略。
6. Redis 的持久化机制有哪些?
Redis提供了RDB(Redis DataBase)和AOF(append only file)两种持久化机制。
6.1 RDB
RDB持久化,是指在指定的时间间隔内,执行指定次数的写操作,将内存中的数据集快照写入磁盘中,它是Redis默认的持久化方式。执行完操作后,在指定目录下会生成一个dump.rdb文件,Redis 重启的时候,通过加载dump.rdb文件来恢复数据。RDB触发机制主要有以下几种:
RDB 的优点:
- RDB是一个紧凑压缩的二进制文件,存储效率较高
- 适合大规模的数据恢复场景,如备份,全量复制等,RDB恢复数据的速度要比AOF快很多
RDB缺点:
- 没办法做到实时持久化/秒级持久化。
- 新老版本存在RDB格式兼容问题
6.2 AOF
AOF持久化,采用日志的形式来记录每个写操作并追加到文件中,重启时再重新执行AOF文件中的命令来恢复数据。它主要解决数据持久化的实时性问题,默认是不开启的。
AOF的优点:
- 数据的一致性和完整性更高
AOF的缺点:
- AOF记录的内容越多,文件越大,数据恢复变慢。
7.怎么实现Redis的高可用(三种模式)?
Redis 实现高可用有三种部署模式:主从模式,哨兵模式,集群模式。
7.1 主从模式
主从模式中,Redis部署了多台机器,有主节点,负责读写操作,有从节点,只负责读操作。从节点的数据来自主节点,实现原理就是主从复制机制。
主从复制包括全量复制,增量复制两种。
7.1.1全量复制
一般当slave第一次启动连接master,或者认为是第一次连接,就采用全量复制,全量复制流程如下:
redis2.8版本之后,已经使用psync来替代sync,因为sync命令非常消耗系统资源,psync的效率更高。
7.1.2 增量复制
slave与master全量同步之后,master上的数据,如果再次发生更新,就会触发增量复制。
当master节点发生数据增减时,会把用户执行的命令发送到所有的slave节点,让slave节点执行。流程如下:
7.2 哨兵模式
哨兵(sentinel) 是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的master并将所有slave连接到新的master。
7.2.1哨兵的作用(哨兵工作原理):
- 1.监控
不断的检查master和slave是否正常运行。
master存活检测、master与slave运行情况检测 - 2.通知(提醒)
当被监控的服务器出现问题时,向其他(哨兵间,客户端)发送通知。 - 3.自动故障转移
断开master与slave连接,选取一个slave作为master,将其他slave连接到新的master,并告知客户端新的服 务器地址
注意:
哨兵也是一台redis服务器,只是不提供数据服务,哨兵之间也会相互监控,从而达到高可用。
通常哨兵配置数量为单数。
7.3 cluster集群模式
集群就是使用网络将若干台计算机联通起来,并提供统一的管理方式,使其对外呈现单机的服务效果。
7.3.1 集群作用:
- 分散单台服务器的访问压力,实现负载均衡
- 分散单台服务器的存储压力,实现可扩展性
- 降低单台服务器宕机带来的业务灾难
8. 使用过Redis分布式锁嘛?有哪些注意点呢?
lua脚本如下:
if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end;
一般情况下,已经可以使用这种实现方式。但是存在锁过期释放了,业务还没执行完的问题(实际上,估算个业务处理的时间,一般没啥问题了)。
错误实现:
- 命令setnx + expire分开写:
执行完setnx加锁,正要执行expire设置过期时间时,进程crash掉或者要重启维护了,那这个锁就“长生不老”了,别的线程永远获取不到锁啦,所以分布式锁不能这么实现。 - set ex px nx + 校验唯一随机值,再删除:
判断当前线程加的锁和释放锁是不是一个原子操作。如果调用jedis.del()释放锁的时候,可能这把锁已经不属于当前客户端,会解除他人加的锁。
9. 使用过Redisson嘛?说说它的原理
分布式锁可能存在锁过期释放,业务没执行完的问题。有些小伙伴认为,稍微把锁过期时间设置长一些就可以啦。其实我们设想一下,是否可以给获得锁的线程,开启一个定时守护线程,每隔一段时间检查锁是否还存在,存在则对锁的过期时间延长,防止锁过期提前释放。
当前开源框架Redisson就解决了这个分布式锁问题。我们一起来看下Redisson底层原理是怎样的吧:
只要线程一加锁成功,就会启动一个watch dog看门狗,它是一个后台线程,会每隔10秒检查一下,如果线程1还持有锁,那么就会不断的延长锁key的生存时间。因此,Redisson就是使用Redisson解决了锁过期释放,业务没执行完问题。
10. MySQL与Redis 如何保证双写一致性
外部链接: redis缓存为什么要延时双删
10.1 缓存为啥是删除,⽽不是更新?
如果是更新,存在分布式事务问题,可能出现修改了缓存,数据库修改失败的情况。只是删除缓存的话,就算数据库修改失败,下次查询会直接取数据库的数据,也不会出现脏数据。
10.2 延时双删是什么?
就是在增删改某实体类的时候,要对该实体类的缓存进行清空,清空的位置在数据库操作方法的前后。
流程:
- 先删除缓存
- 再更新数据库
- 休眠一会(比如1秒),再次删除缓存。
这个休眠时间 = 读业务逻辑数据的耗时 + 几百毫秒。为了确保读请求结束,写请求可以删除读请求可能带来的缓存脏数据。这种方案只有休眠那一会(比如就那1秒),可能有脏数据,一般业务也会接受的。
11. 聊聊Redis 事务机制
Redis通过MULTI、EXEC、WATCH等一组命令集合,来实现事务机制。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
简言之,Redis事务就是顺序性、一次性、排他性的执行一个队列中的一系列命令。
Redis执行事务的流程如下:
开始事务(MULTI)
命令入队
执行事务(EXEC)、撤销事务(DISCARD )
布隆过滤器
布隆过滤器是一种占用空间很小的数据结构,它由一个很长的二进制向量和一组Hash映射函数组成,它用于检索一个元素是否在一个集合中,空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
布隆过滤器原理是?假设我们有个集合A,A中有n个元素。利用k个哈希散列函数,将A中的每个元素映射到一个长度为a位的数组B中的不同位置上,这些位置上的二进制数均设置为1。如果待检查的元素,经过这k个哈希散列函数的映射后,发现其k个位置上的二进制数全部为1,这个元素很可能属于集合A,反之,一定不属于集合A。
Redis经典面试题总结相关推荐
- Redis经典面试题
本文分享一些Redis相关的经典面试题,看下你是不是都掌握了. 文章目录 Redis Redis redis优化策略 redis除了做缓存还能做什么? 说说redis持久化方式?分别优缺点是什么?re ...
- 2W字!详解20道Redis经典面试题!(珍藏版)
前言 金九银十即将到来,整理了20道经典Redis面试题,希望对大家有帮助. 1. 什么是Redis?它主要用来什么的? Redis,英文全称是Remote Dictionary Server(远程字 ...
- 2W字详解20道Redis经典面试题(珍藏版)
给大家整理了20道经典Redis面试题,希望对大家有帮助. 1. 什么是Redis?它主要用来什么的? Redis,英文全称是Remote Dictionary Server(远程字典服务),是一个开 ...
- 收集Redis 经典面试题
本文的面试题如下: Redis 持久化机制 缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级等问题 热点数据和冷数据是什么 Memcache与Redis的区别都有哪些? 单线程的redis为什么这么快 ...
- 2W字!详解20道Redis经典面试题!(珍藏版)二
9.1 主从模式 主从模式中,Redis部署了多台机器,有主节点,负责读写操作,有从节点,只负责读操作.从节点的数据来自主节点,实现原理就是主从复制机制 主从复制包括全量复制,增量复制两种.一般当sl ...
- 2W字 详解20道Redis经典面试题(珍藏版)
1. 什么是Redis?它主要用来什么的? Redis,英文全称是Remote Dictionary Server(远程字典服务),是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化 ...
- Redis 经典面试题:Redis 面试连环炮【Redis必知必会】
Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行各种刁难. Redis有哪些数据结构? 字符串String.字典Hash.列表List ...
- Java经典面试题整理及答案详解(四)
简介: Java经典面试题第四弹来啦!本节小编整理了关于Java开发框架常见的面试题,希望大家多多怜惜,一起进步- 1.SpringMVC返回值,使用SpringMVC的时候我看到两种风格的开发,一种 ...
- java面试题_阿里大厂流出的数百道 Java 经典面试题
BAT 常问的 Java基础39道常见面试题 1.八种基本数据类型的大小,以及他们的封装类 2.引用数据类型 3.Switch能否用string做参数 4.equals与==的区别 5.自动装箱,常量 ...
最新文章
- python使用imbalanced-learn的AllKNN方法进行下采样处理数据不平衡问题
- android英文文献翻译,有关android技术英文文献翻译
- 线程创建后,立刻调用CloseHandle的原因
- iview图表_【技术博客】iview常用工具记录
- 动态时间规整-DTW算法
- 语句:分支语句、switch case ——7月22日
- 帆软地址栏传参,实例
- vscode 怎么编辑sphinx_如何在vs Code 中编辑和调试Stata程序
- Java 中的几种线程池,你之前用对了吗,互联网 面试官 如何面试
- 智汇华云 | 集群自动化部署服务流程之自动化集群配置(下)
- Rotate Array旋转数组
- [.NET] EF LINQ 按时间对数据分类汇总
- plsql去除字段中空格_PLSQL 数据中去掉 字段有空格 回车 换行
- 整理了上千个Python类库,简直太酷啦!
- Linux下清除磁盘分区及残留raid信息
- Java常用类学习笔记
- CFLOW-AD:通过条件归一化流量进行实时无监督的异常检测与定位
- c 语言 树根 函数专题
- JPEG数据转YUV数据应用实例
- VB实现向窗口发送按键消息
热门文章
- 【笔记】H.265/HEVC 视频编码(二)——数字视频格式
- HTML5+CSS大作业——个人图库网页设计(5页)
- OpenSceneGraph源码分析:osgQt模块
- 8086-小写字母转大写字母
- 极限题型二:求数列极限常见题型
- 国内有哪些质量高的java社区
- 上海5月社保费缴纳时间安排,缴费减免了多少?应该缴纳多少?
- 【论文阅读】WaterGAN
- ie浏览器的html在哪里,Win10系统下ie浏览器在哪?怎么打开IE浏览器?
- 【ESP32】17.DS1302实时时钟模块实验(ThreeWire库 / RtcDS1302库)