前言
共20题。
项目中为什么用Redis?
-
操作速度快:数据都保存在内存中;
-
数据类型丰富 :支持
string,list,set,Zset,hash等数据类型; -
使用场景丰富 :缓存,消息队列,按
key设置过期时间,过期后自动删除。
Redis的基础数据类型有哪些?
Redis最常见的数据类型有5种,分别是String、List、Hash、Set、ZSet
-
String:字符串类型,场景:计数、缓存文本内容等;
-
List:底层是链表,增删容易随机访问困难。场景:消息队列;
-
Hash :类似于
Java中的HashMap,存储对象。场景:系统中对象数据的存储; -
Set:无序集合;
-
ZSet:有序集合,且集合中每个元素关联一个分数,可以根据分数进行排序。
Redis为什么这么快?
-
纯内存操作 :
Redis的绝大部分请求是纯粹的内存操作,非常快速; -
单线程 :
Redis的核心部分是单线程运行的,避免了不必要的上下文切换,也不存在线程切换导致的CPU消耗; -
使用I/O多路复用模型 :利用单个线程来同时监听多个
Socket,并在某个Socket可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。 -
数据类型 :
redis内置了多种优化过的数据类型(5种基本数据类型+5种复杂数据类型 ),这些数据类型的性能非常高。
Redis的过期删除策略有哪些?
Redis的过期删除策略有:
-
惰性删除 :只会在取出
key的时候才对数据进行过期检查,过期了就删除; -
定期删除 :每隔一段时间抽取一批
key执行删除过期key操作。
两者相比,定期删除 对内存更加友好,惰性删除 对CPU更加友好。
Redis采用的是定期删除 +惰性/懒汉式删除。
Redis的内存淘汰策略有哪些?
内存淘汰策略指的是:当Redis的内存已经存满,又有新的数据需要保存时的处理方案。
Redis的内存淘汰策略有:
- 默认策略:直接报错;
- 随机淘汰策略;
- 淘汰最少使用策略。
Redis持久化RDB和AOF的区别?
-
RDB 采用的是定期更新的方式,磁盘上保存的就是
Redis的内存快照。文件较小,数据恢复速度较快,但存在丢失数据的风险; -
AOF 磁盘保存的是所有执行的指令,在下次
Redis重启时,只需要将指令重写一遍即可。相对完整但文件较大,数据恢复的速度较慢。
实践中可以同时开启
RDB和AOF持久化机制。Redis重启时先使用AOF日志进行恢复,然后再使用RDB快照进行备份。定期进行RDB快照的备份,以便在需要时进行全量数据的恢复,提高数据的可靠性、恢复能力以及持久化能力。
RDB期间可以同时处理写请求吗?
可以,bgsave快照备份时不耽误写,但save不行。
-
具体来说,就是
Redis在持久化时会产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求; -
当主线程执行写指令修改数据的时候,这个数据就会复制一份副本,然后修改副本中的数据,
RDB结束后,主进程读取这个副本数据写到RDB文件; -
这既保证了快照的完整性,也允许主线程同时对数据进行修改,避免了对正常业务的影响。
Redis集群有哪些方案?
Redis集群主要有三种方案,分别是主从 、哨兵 和分片集群。
-
主从 集群主要用来解决
Redis的并发问题,实现读写分离。一个主节点负责写,多个从节点负责读,主节点的数据会实时同步给从节点; -
哨兵 集群主要用来解决
Redis的高可用问题。哨兵会监控集群中节点状态,并在主节点出现问题时重新选主,但他不保存数据; -
分片 集群主要用来解决
Redis的海量数据存储和高并发写的问题--哈希槽。要求有多个主节点,然后写入的数据会经过计算落到其中一个上。
如何保证Redis数据与MySQL一致?
常见的有三种:
-
同步双写 :即在程序更新完
MySQL之后后立即同步更新redis; -
异步监听 :即通过
Canal监听MySQL的binlog日志变化,然后再通过程序将变化的数据更新数据到Redis; -
MQ异步 :即程序在更新完
MySQL后,发送一条消息到MQ中,然后再通过一个程序监听MQ,获取到消息,然后更新Redis。
什么是缓存预热?
缓存预热指的是:提前将数据放进Redis中--先查Redis再查MySQL,避免高并发访问时,对数据库造成的压力。
缓存预热解决方案主要有下面几个:
-
数据量不大的时候,工程启动的时候进行加载缓存动作;
-
数据量大的时候,设置一个定时任务脚本,进行缓存的刷新;
-
数据量太大的时候,优先保证热点数据进行提前加载到缓存。
什么是缓存穿透,怎么解决?
缓存穿透指的是:当查询redis中未存在的数据时就会去MySQL中查询,然后大量请求进入MySQL就会导致MySQL承受不了压力而宕机。常用的解决方案有:
-
对传入参数进行判断是否合法;
-
对数据库未查询到的
id信息也存入redis,这样下次查询就会从redis中获取; -
使用布隆过滤器 :以较小内存为代价的,用于检测大量元素是否存在的算法,核心原理是二进制数组 + 哈希运算,可以通过
Redisson、Guava、Hutool来实现。
什么是缓存击穿,怎么解决?
缓存击穿指的是:当redis中一个热点数据的过期时间到了,然后还有大量请求来访问这个热点数据,但redis已经对该数据做了过期处理,这个时候就会访问MySQL当大量请求进入MySQL,就会导致MySQL承受不了压力而宕机。
常用的解决方案有:
-
不对热点数据设置过期时间;
-
布隆过滤器。
什么是缓存雪崩,怎么解决?
当redis中的大量数据都是同一过期时间,当这些数据同时过期,这时候然后大量请求过来在redis中没有拿到数据,这些请求就会去MySQL中获取数据,导致MySQL承受不了压力而宕机。
解决方案:给这些数据设置随机过期时间或者不进行过期处理。
用过Redis的事务吗?
没有用过,他本身没有事务概念但一些命令组合起来可以起到事务的效果。
什么类型的数据适合往redis里放?
- 热点数据:也即需频繁访问的数据;
- 会话数据:存储用户会话信息如登录状态;
- 消息队列:存储消息队列中的消息。
redis除了5种基本数据类型,还有哪些类型?
除了5种基本数据类型,redis还有5种特殊数据类型:
- GEO地理位置类型,用于存储地理位置信息并进行相关操作,如添加地理位置的坐标、获取地理位置的坐标、计算两个位置之间的距离等。
- HyperLogLog类型 用于基数统计,基数指的是去重后元素出现的个数,
HyperLogLog类型的优点在于输入元素的数量或体积很大时,计算基数所需的空间总是固定且很小; - Bitmap :位图,是由
0和1状态表示的二进制位的bit数组,用于处理大量数据的布尔值状态。可以用作布隆过滤器的数据类型。 - bitfield类型:可以一次性对多个比特域进行操作。
- Stream类型 :
Stream类型是redis5.0新增加的数据结构,主要用于消息队列。Stream类型提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每个客户端的访问位置,保证消息不丢失。
你们的redis是什么版本?
实际开发常用版本7。
布隆过滤器会不会出现判断不准确的情况?
布隆过滤器可能会误判,原因在于它使用了哈希算法,Hash算法存在着一定的碰撞几率。Hash碰撞的含义是不同的输入值经过hash得到相同的hash结果。
当一个不存在于redis的数据经过布隆过滤器时,先根据哈希算法计算出其在数组上的位置,此时该哈希槽可能因为其他数据计算出相同位置,该位置数据状态已经变成1(1表示数据存在,0表示数据不存在),因此布隆过滤器认为该数据存在,这就产生了误判。
但是,如果布隆过滤器判断这个元素不在redis时,它就一定不在redis中,因此非常适合解决缓存穿透的问题。
关于io多路复用,redis在windows和linux上的性能表现会不会不同?
redis在linux上的性能表现高于windows,主要的区别是操作系统内核的不同。
redis在linux上通过单线程epoll非阻塞同步模型 + 自己开发的一个事件框架实现了io多路复用模型,windows上则没有epoll。
为什么使用redis存储消息队列的消息?
因为redis直接操作内存非常快速,且可以设置key的过期时间,还有专门存储消息队列的数据类型Stream,Stream类型能够实现消息的持久化和主备复制,可以让任何客户端访问任何时刻的数据,并且能记住每个客户端的访问位置,保证消息不丢失