面试准备:Redis常见面试题汇总

1.介绍一下Redis

Redis 是一款使用 C 语言编写的高性能 key-value 数据库

特点:

  • 性能极高,能到 100000 次/s 读写速度
  • 支持数据的持久化,对数据的更新采用Copy-on-write技术,可以异步地保存到磁盘上
  • 丰富的数据类型,String(字符串)、List(列表)、Hash(字典)、Set(集合)、Sorted Set(有序集合)
  • 原子性:Redis 的所有操作都是原子性的,多个操作通过 MULTI 和 EXEC 指令支持事务
  • 丰富的特性:key 过期、publish/subscribe、notify
  • 支持数据的备份,快速的主从复制
  • 节点集群,很容易将数据分布到多个Redis实例中
  • 单线程:避免了不必要的上下文切换和竞争条件

用途:
高速缓存。
分布式锁。
单点登录共享session。
计数器。

2.Redis为什么这么快?

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单高效,如 Hash、跳表等。

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

3.Redis支持哪些数据类型?

Redis 支持五种数据类型

string:字符串
hash:哈希
list:列表
set:集合
sorted set:有序集合

4.Redis与Memcached的区别?

暂不做了解。

5.Redis跳表是什么?

跳跃表基于有序单链表,在链表的基础上,每个结点不只包含一个指针,还可能包含多个指向后继结点的指针,这样就可以跳过一些不必要的结点,从而加快查找、删除等操作。
在这里插入图片描述

6.什么是冷热数据分离?什么是VM机制?

Redis使用到了VM, 通过VM功能可以实现冷热数据分离。使热数据仍在内存中,冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。

冷数据即是那些不经常访问、但又无法删除的信息。

7.Redis过期键的删除策略有哪些?

惰性删除:不主动删除过期键,从键空间中获取键时,都检查取得的键是否过期,过期则删除;没过期则返回
定期删除:每隔一段时间对数据库进行一次检查,删除里面的过期键。删除多少过期键、检查多少个数据库,由算法决定。

参考:Java架构直通车——Redis缓存过期处理与内存淘汰机制

8.说说Redis的同步机制?

2.8 版以前

Redis 通过同步(sync)和指令传播(command propagate)两个操作完成同步

同步(sync):将从节点的数据库状态更新至与主节点的数据库状态一致

从节点向主节点发送 SYNC 指令
收到 SYNC 指令,主节点执行 BGSAVE 指令,在后台生成一个 RDB 文件,并使用一个缓冲区记录从现在开始执行的所有写指令
主节点 BGSAVE 指令执行后,会将生成的 RDB 文件发送给从节点
从节点接收、载入 RDB 文件,将数据库状态更新至主节点执行 BGSAVE 指令时的数据库状态
从节点加载完 RDB 文件,通知主节点将记录在缓冲区里面的所有写指令发送给从节点,从节点执行这些写指令,将数据库状态更新至主节点当前数据库状态

指令传播(command propagate):主节点数据被修改,会主动向从节点发送执行的写指令,从节点执行之后,两个节点数据状态又保持一致

为了解决主从节点断线复制低效的问题(SYNC过程中生成、传输、载入 RDB 文件耗费大量 CPU、内存、磁盘 IO 资源),2.8 版开始新增 PSYNC 指令。

PSYNC 具有两种模式

完整重同步(full resynchronization),与SYNC过程基本一致
部分重同步(partial resynchronization),借助复制偏移量、复制积压缓冲区、服务器运行 ID ,完成主从节点断开连接后,从节点重连主节点后,条件允许,主节点将连接断开期间执行的写指令发送给从节点,从节点接收并执行写指令,将数据库更新至主节点当前状态

9.Pipeline有什么好处?

多个指令之间没有依赖关系,可以使用 pipeline 一次性执行多个指令,减少 IO,缩减时间。

10.Redis实现分布式锁?

参考:Java架构直通车——基于Redis的Set NX实现分布式锁

11.Redis实现幂等性?

为需要保证幂等性的每一次请求创建一个唯一标识token, 先获取token, 并将此token存入redis, 请求接口时, 将此token放到header或者作为请求参数请求接口, 后端接口判断redis中是否存在此token:

如果存在, 正常处理业务逻辑, 并从redis中删除此token, 那么, 如果是重复请求, 由于token已被删除, 则不能通过校验, 返回请勿重复操作提示。

12. 接触过哪些Redis客户端?

Redisson

优点:

实现了分布式特性和可扩展的 Java 数据结构,适合分布式开发
API 线程安全
基于 Netty 框架的事件驱动的通信,可异步调用
缺点:

API 更抽象,学习使用成本高

Jedis

优点:

提供了比较全面的 Redis 操作特性的 API
API 基本与 Redis 的指令一一对应,使用简单易理解
缺点:

同步阻塞 IO
不支持异步
线程不安全

Lettuce

优点:

线程安全
基于 Netty 框架的事件驱动的通信,可异步调用
适用于分布式缓存
缺点:

API 更抽象,学习使用成本高

13.Redis哈希槽?

Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念。

Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 算法计算的结果,对 16384 取模后放到对应的编号在 0-16383 之间的哈希槽,集群的每个节点负责一部分哈希槽

14.Redis 集群会有写操作丢失吗?

以下情况可能导致写操作丢失:

过期 key 被清理
最大内存不足,导致 Redis 自动清理部分 key 以节省空间
主库故障后自动重启,从库自动同步
单独的主备方案,网络不稳定触发哨兵的自动切换主从节点,切换期间会有数据丢失

15.如何保证Redis中存的都是热点数据?

Redis存储在内存中的数据升到配置大小时,就进行数据淘汰

使用 allkeys-lru 策略,从数据集(server.db[i].dict)中挑选最近最少使用的数据优先淘汰,即可满足保存热点数据

16.缓存穿透、击穿、雪崩?

参考:Java架构直通车——Redis缓存穿透/击穿/雪崩

17.热点key?

缓存中的某些Key(可能对应用与某个促销商品)对应的value存储在集群中一台机器,使得所有流量涌向同一机器,成为系统的瓶颈,该问题的挑战在于它无法通过增加机器容量来解决。(当key失效的时候,大量的线程构建缓存,导致负载增加)

解决方案:

  1. 客户端热点key缓存:将热点key对应value并缓存在客户端本地,并且设置一个失效时间。对于每次读请求,将首先检查key是否存在于本地缓存中,如果存在则直接返回,如果不存在再去访问分布式缓存的机器。
  2. 将热点key分散为多个子key,然后存储到缓存集群的不同机器上,这些子key对应的value都和热点key是一样的。当通过热点key去查询数据时,通过某种hash算法随机选择一个子key,然后再去访问缓存机器,将热点分散到了多个子key上。
  3. 为每个 value 设置一个逻辑过期时间,当发现超过逻辑过期时间后,会使用单独的线程去构建缓存。缓存层面没有设置过期时间(这种方案可以解决大量线程等待的问题,但它可能导致数据不一致的问题)
  4. 针对热点key失效,大量线程构建缓存(使用分布式锁,只让一个线程构建缓存,可以解决这个问题)。

18.大Key(Big Key)?

Redis使用过程中经常会有各种大key的情况, 比如单个简单的key存储的value很大。
由于redis是单线程运行的,如果一次操作的value很大会对整个redis的响应时间造成负面影响,导致IO网络拥塞。

解决:

将整存整取的大对象,分拆为多个小对象。可以尝试将对象分拆成几个key-value, 使用multiGet获取值,这样分拆的意义在于分拆单次操作的压力,将操作压力平摊到多个redis实例中,降低对单个redis的IO影响;

19.无底洞问题?

暂时不做了解。

20.缓存与数据库一致性问题?

参考:缓存架构
参考:分布式DB与Cache一致性

发布了431 篇原创文章 · 获赞 329 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/No_Game_No_Life_/article/details/105513768