Redis面试题全面解析:从基础到底层实现
Redis作为当今最流行的内存数据库之一,是后端开发岗位面试中的高频考点。本文将系统整理Redis面试中常见的基础、中级和底层实现问题,帮助开发者全面准备Redis相关面试。
一、Redis基础问题
1. Redis是什么?主要特点是什么?
Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,可以用作数据库、缓存和消息中间件。主要特点包括:
-
基于内存操作,读写性能极高
-
支持丰富的数据结构(string, hash, list, set, sorted set等)
-
支持数据持久化(RDB和AOF两种方式)
-
支持主从复制和高可用(Redis Sentinel)
-
支持事务和Lua脚本
-
支持键过期和发布订阅功能
2. Redis支持哪些数据类型?各自的使用场景?
Redis支持5种核心数据类型:
-
String(字符串):最简单的类型,可以存储文本、数字或二进制数据。常用于缓存、计数器等场景。
-
Hash(哈希):键值对集合,适合存储对象。如用户信息{name:"John", age:30}。
-
List(列表):有序可重复的字符串集合,支持双向操作。可用于消息队列、最新消息排行等。
-
Set(集合):无序且唯一的字符串集合。适合标签系统、共同好友等场景。
-
Sorted Set(有序集合):在Set基础上为每个元素关联一个分数(score),可排序。适用于排行榜、带权重的队列等。
3. Redis的持久化机制有哪些?有什么区别?
Redis提供两种持久化方式:
RDB(Redis Database):
-
定时生成数据快照
-
二进制格式,文件紧凑,恢复速度快
-
可能丢失最后一次快照后的数据
-
适合备份和灾难恢复
AOF(Append Only File):
-
记录所有写操作命令
-
可配置不同fsync策略(无fsync/每秒fsync/每次写操作fsync)
-
文件较大且恢复较慢
-
数据安全性更高
生产环境通常两者结合使用,用AOF保证数据不丢失,用RDB做冷备。
4. Redis如何实现过期键的删除?
Redis采用两种策略删除过期键:
-
惰性删除:当访问一个键时,Redis会检查它是否过期,如果过期就立即删除。
-
定期删除:Redis定期随机测试一些设置了过期时间的key,删除其中已过期的key。
二、Redis中级问题
1. Redis事务是如何工作的?
Redis事务通过MULTI、EXEC、DISCARD和WATCH命令实现:
-
MULTI:标记事务开始
-
EXEC:执行事务中的所有命令
-
DISCARD:取消事务
-
WATCH:监视一个或多个key,如果在事务执行前这些key被改动,则事务被打断
特点:
-
事务中的命令会按顺序串行执行
-
不支持回滚(Redis认为失败是编程错误,应在开发环境解决)
-
没有隔离级别概念
2. Redis的发布订阅功能如何使用?
Redis提供发布/订阅消息模式,相关命令:
-
SUBSCRIBE channel [channel...]:订阅一个或多个频道
-
PUBLISH channel message:向指定频道发布消息
-
UNSUBSCRIBE [channel [channel...]]:退订频道
-
PSUBSCRIBE pattern [pattern...]:订阅匹配给定模式的所有频道
特点:
-
消息是即时的,不会持久化
-
订阅者只能收到订阅后发布的消息
-
适合简单的消息通知场景
3. Redis如何实现分布式锁?
Redis实现分布式锁的常用方式:
-
SETNX + EXPIRE:
SETNX lock_key unique_value EXPIRE lock_key 10
问题:SETNX和EXPIRE不是原子操作
-
SET扩展参数(推荐):
SET lock_key unique_value NX PX 10000
NX表示只有key不存在时才设置,PX设置过期时间(毫秒)
-
RedLock算法:
-
获取当前时间
-
依次尝试从多个独立的Redis实例获取锁
-
计算获取锁花费的时间,只有当大多数实例获取成功且总耗时小于锁有效期才认为成功
-
释放锁时向所有实例发送释放命令
-
4. Redis的Pipeline有什么作用?
Pipeline可以将多个命令一次性发送到服务器,减少网络往返时间(RTT),显著提高性能。
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import java.util.List;public class RedisPipelineExample {public static void main(String[] args) {// 创建Jedis连接try (Jedis jedis = new Jedis("localhost", 6379)) {// 开启PipelinePipeline pipe = jedis.pipelined();// 添加多个命令到Pipelinepipe.set("foo", "bar");pipe.get("foo");// 执行Pipeline中的所有命令并获取结果List<Object> results = pipe.syncAndReturnAll();// 处理结果// 第一个结果是SET命令的返回:"OK"System.out.println("SET result: " + results.get(0));// 第二个结果是GET命令的返回:"bar"System.out.println("GET result: " + results.get(1));} catch (Exception e) {e.printStackTrace();}}
}
注意:
-
Pipeline中的命令是批量执行的,不是原子性的
-
适合需要执行多个命令但不需要事务的场景
-
合理设置批量大小,避免单次传输数据过大
三、Redis底层实现问题
1. Redis的底层数据结构有哪些?
Redis的每种数据类型都有其底层实现:
-
String:简单动态字符串(SDS)
-
List:3.2版本前是双向链表或压缩列表(ziplist),之后统一为quicklist
-
Hash:压缩列表或哈希表(dict)
-
Set:整数集合(intset)或哈希表
-
Sorted Set:压缩列表或跳表(skiplist)+哈希表
2. Redis为什么快?
Redis高性能的原因:
-
基于内存:数据存储在内存中,读写操作直接操作内存
-
IO多路复用:使用epoll/kqueue等机制实现高并发的网络IO
-
单线程模型:避免多线程上下文切换和竞争条件
-
高效数据结构:精心设计的数据结构如SDS、跳跃表等
-
优化编码:针对不同场景采用不同编码方式节省内存
3. Redis的内存淘汰策略有哪些?
当内存不足时,Redis提供多种淘汰策略:
-
noeviction:不淘汰,返回错误(默认)
-
allkeys-lru:从所有key中淘汰最近最少使用的
-
volatile-lru:从设置了过期时间的key中淘汰LRU
-
allkeys-random:随机淘汰所有key
-
volatile-random:随机淘汰过期key
-
volatile-ttl:淘汰剩余生存时间最短的key
4. Redis的渐进式rehash是如何工作的?
Redis哈希表在扩容时会进行rehash,为避免一次性rehash导致服务不可用,采用渐进式rehash:
-
为ht[1]分配空间,字典同时持有ht[0]和ht[1]
-
维持一个rehashidx计数器,初始为0
-
每次对字典执行操作时,将ht[0]在rehashidx索引上的所有键值对rehash到ht[1],rehashidx++
-
最终ht[0]为空表,释放ht[0],将ht[1]设置为ht[0]
在此期间:
-
查找操作会同时查找两个表
-
新增操作只保存到ht[1]
-
删除、更新操作在两个表上进行
5. Redis的跳表(skiplist)实现原理?
跳表是一种有序数据结构,通过在每个节点维持多个指向其他节点的指针实现快速访问。Redis使用跳表作为有序集合的底层实现之一。
特点:
-
由多层组成,最底层包含所有元素
-
每个节点包含多个指针,指向同层和下一层的节点
-
查找时间复杂度平均O(logN),最坏O(N)
-
相比平衡树实现简单且插入删除更高效
四、Redis实战与优化
1. Redis常见性能问题和解决方案
-
大key问题:
-
问题:单个key存储数据过大,导致操作延迟高、阻塞其他请求
-
解决:拆分大key、使用SCAN系列命令替代KEYS、避免使用大value
-
-
热key问题:
-
问题:某些key访问量极高,造成单节点压力过大
-
解决:本地缓存、多副本、使用Redis集群分散压力
-
-
缓存穿透:
-
问题:大量请求查询不存在的数据,绕过缓存直接访问数据库
-
解决:布隆过滤器、缓存空对象
-
-
缓存雪崩:
-
问题:大量缓存同时失效,请求直接打到数据库
-
解决:设置不同的过期时间、使用锁或队列控制读数据库的线程数
-
2. Redis集群方案有哪些?
-
Redis Sentinel:
-
监控、通知、自动故障转移
-
解决高可用问题
-
不解决数据分片问题
-
-
Redis Cluster:
-
官方提供的分布式解决方案
-
数据分片(16384个slot)
-
主从复制和高可用
-
节点间使用Gossip协议通信
-
-
客户端分片:
-
由客户端实现分片逻辑
-
简单但扩展性和可用性较差
-
-
代理分片:
-
如Twemproxy、Codis等
-
客户端连接代理,由代理实现分片
-
五、总结
Redis面试问题通常围绕其数据结构、持久化、高可用、分布式和底层实现展开。掌握这些知识点不仅有助于面试,也能帮助我们在实际工作中更好地使用Redis。建议在理解原理的基础上,结合实际使用经验,这样才能在面试中游刃有余。
相关文章:
Redis面试题全面解析:从基础到底层实现
Redis作为当今最流行的内存数据库之一,是后端开发岗位面试中的高频考点。本文将系统整理Redis面试中常见的基础、中级和底层实现问题,帮助开发者全面准备Redis相关面试。 一、Redis基础问题 1. Redis是什么?主要特点是什么? Re…...

【性能测试】jvm监控
使用本地jvisualvm远程监控服务器 参考文章:https://blog.csdn.net/yeyuningzi/article/details/140261411 jvisualvm工具默认是监控本地jvm,如果需要监控远程就要修改配置参数 1、先查看是否打开 ps -ef|java 如果打开杀掉进程 2、进入项目服务路径下…...

Uniapp开发鸿蒙应用时如何运行和调试项目
经过前几天的分享,大家应该应该对uniapp开发鸿蒙应用的开发语法有了一定的了解,可以进行一些简单的应用开发,今天分享一下在使用uniapp开发鸿蒙应用时怎么运行到鸿蒙设备,并且在开发中怎么调试程序。 运行 Uniapp项目支持运行到…...

QT+RSVisa控制LXI仪器
1.下载并安装visa R&SVISA - Rohde & Schwarz China 2.安装后的目录说明 安装了64位visa会默认把32位的安装上; 64位库和头文件目录为:C:\Program Files\IVI Foundation 32位库和头文件目录为:C:\Program Files (x86)\IVI Foundation…...
PHP8.0版本导出excel失败
环境:fastadmin框架,不是原版接手的项目。PHP8.0,mysql5.7. code // 创建一个新的 Spreadsheet 对象 $spreadsheet new Spreadsheet(); $worksheet $spreadsheet->getActiveSheet();// 设置表头 $worksheet->setCellValue(A1, ID); $worksheet…...
GO语言学习(五)
GO语言学习(五) 前面我们已经学了一些关于golang的基础知识,从这一期开始,我们就来讲解一下基于golang为后端的web开发,首先这一期为一些golang为后端的web开发基础讲解,我们将会从web的工作方式、golang如…...
js不同浏览器标签页、窗口或 iframe 之间可以相互通信
一、创建一个广播通道 // 创建一个名为 vue-apps-channel 的广播通道 const channel new BroadcastChannel(vue-apps-channel);二、发送消息 channel.postMessage({type: popup, message: false}); 三、接收消息(也需要创建广播通道) // 也创建一个…...

springboot3+vue3融合项目实战-大事件文章管理系统-文章分类也表查询(条件分页)
在pojo实体类中增加pagebean实体类 Data NoArgsConstructor AllArgsConstructor public class PageBean <T>{private Long total;//总条数private List<T> items;//当前页数据集合 }articlecontroller增加代码 GetMappingpublic Result<PageBean<Article&g…...

Canvas进阶篇:鼠标交互动画
Canvas进阶篇:鼠标交互动画 前言获取鼠标坐标鼠标事件点击事件监听代码示例效果预览 拖动事件监听代码示例效果预览 结语 前言 在上一篇文章Canvas进阶篇:基本动画详解 中,我们讲述了在Canvas中实现动画的基本步骤和动画的绘制方法。本文将进…...
Mac下载bilibili视频
安装 安装 yt-dlp brew install yt-dlp安装FFmpeg 用于合并音视频流、转码等操作 brew install ffmpeg使用 下载单个视频 查看可用格式 yt-dlp -F --cookies-from-browser chrome "https://www.bilibili.com/video/BV15B4y1G7F3?spm_id_from333.788.recommend_more_vid…...
Unity editor文件数UI(支持勾选框)
unity editor文件数(支持勾选框) 使用的时候new一个box即可 using Sirenix.OdinInspector; using Sirenix.OdinInspector.Editor; using System; using System.Collections; using System.Collections.Generic; using UnityEngine;[Serializable] publ…...

【Node.js】Web开发框架
个人主页:Guiat 归属专栏:node.js 文章目录 1. Node.js Web框架概述1.1 Web框架的作用1.2 Node.js主要Web框架生态1.3 框架选择考虑因素 2. Express.js2.1 Express.js概述2.2 基本用法2.2.1 安装Express2.2.2 创建基本服务器 2.3 路由2.4 中间件2.5 请求…...

使用Vite创建一个动态网页的前端项目
1. 引言 虽然现在的前端更新换代的速度很快,IDE和工具一批批的换,但是我们始终要理解一点基本的程序构建的思维,这些环境和工具都是为了帮助我们更快的发布程序。笔者还记得以前写前端代码的时候,只使用文本编辑器,然…...

系统架构设计师案例分析题——web篇
软考高项系统架构设计师,其中的科二案例分析题为5选3,总分75达到45分即合格。本贴来归纳web设计题目中常见的知识点即细节: 目录 一.核心知识 1.常见英文名词 2.私有云 3.面向对象三模型 4.计网相关——TCP和UDP的差异 5.MQTT和AMQP协…...

MySQL--day5--多表查询
(以下内容全部来自上述课程) 多表查询 1. 为什么要用多表查询 # 如果不用多表查询 #查询员工名为Abel的人在哪个城市工作? SELECT* FROM employees WHERE last_name Abel;SELECT * FROM departments WHERE department_id 80;SELECT * FROM locati…...
【Redis】AOF日志的三种写回机制
目录 1、背景2、appendfsync always(同步写回)【1】工作机制【2】特点【3】实现原理 3、appendfsync everysec(每秒写回,默认配置)【1】工作机制【2】特点【3】实现原理 4、appendfsync no(操作系统控制&am…...

leetcode hot100刷题日记——7.最大子数组和
class Solution { public:int maxSubArray(vector<int>& nums) {//方法一:动态规划//dp[i]表示以i下标结尾的数组的最大子数组和//那么在i0时,dp[0]nums[0]//之后要考虑的就是我们要不要把下一个数加进来,如果下一个数加进来会使结…...

基于Spring Boot和Vue的在线考试系统架构设计与实现(源码+论文+部署讲解等)
源码项目获取联系 请文末卡片dd我获取更详细的演示视频 系统介绍 基于Spring Boot和Vue的在线考试系统。为学生和教师/管理员提供一个高效、便捷的在线学习、考试及管理平台。系统采用前后端分离的架构,后端基于成熟稳定的Spring Boot框架,负责数据处理…...
MySQL Workbench 工具导出与导入数据库:实用指南
目录 一、MySQL Workbench 简介二、导出数据库2.1 打开 MySQL Workbench2.2 数据库导出步骤三、导入数据库3.1 打开 MySQL Workbench3.2 数据库导入步骤四、注意事项五、总结MySQL Workbench 是一款强大的数据库管理和开发工具,它提供了直观的图形界面,方便用户进行数据库的设…...

Android 绘制折线图
用了一段时间的 Jetpack Compose ,感觉写 UI 的效率确实会提升不少 。 配合 AI 编程绘制了一个折线图。供大家学习参考! @Composable fun TemperatureChart() {val timeLabels = listOf("7:00", "8:00", "9:00", "10:00", "11:…...

自建srs实时视频服务器支持RTMP推流和拉流
文章目录 一、整体示意图二、服务器端1.srs简介及架构2.docker方式安装3.k8s方式安装4.端口 三、推流端1.OBS Studio2.ffmpeg推流3.streamlabs苹果手机4.twire安卓手机5.网络推流摄像头 四、拉流端1.vlc2.srs 参考awesome系列:https://github.com/juancarlospaco/aw…...
ubuntu22.04 卸载ESP-IDF
要在Ubuntu 22.04上完全卸载ESP-IDF,请按照以下步骤操作: 卸载ESP-IDF的步骤 删除ESP-IDF目录: # 假设ESP-IDF安装在~/esp/esp-idf目录 rm -rf ~/esp/esp-idf删除ESP-IDF工具链和下载的工具: rm -rf ~/.espressif从PATH中移除ESP…...

Spring IOCDI————(2)
DI详解 我们之前讲了控制反转IOC,也就是bean的存,那么我们还需要Bean的取,就是DI了,DI翻译过来就是依赖注入,啥意思呢,就是我们通过IOC容器,把所有的对象交给Spring管理,我们指定哪…...
80. Java 枚举类 - 使用枚举实现单例模式
文章目录 80. Java 枚举类 - 使用枚举实现单例模式**1️⃣ 为什么用枚举实现单例?****2️⃣ 枚举实现单例模式****3️⃣ 枚举单例如何防止反射攻击?****4️⃣ 枚举单例如何防止反序列化破坏?****5️⃣ 枚举单例 vs 传统单例****6️⃣ 枚举单例…...

融云 uni-app IMKit 上线,1 天集成,多端畅行
融云 uni-app IMKit 正式上线,支持一套代码同时运行在 iOS、Android、H5、小程序主流四端,集成仅需 1 天,并可确保多平台的一致性体验。 融云 uni-app IMKit 在 Vue 3 的高性能加持下开发实现,使用 Vue 3 Composition API&#x…...
Java中的集合详解
下面是文章详细介绍了 Java 集合框架的基本思路、主要接口与实现、各类集合之间的区别与各自的适用场景,以及一些常见的使用技巧和最佳实践,供你参考。 Java中的集合详解 在 Java 开发中,集合(Collection)作为存储和操…...
利用 Java 爬虫根据关键词获取某手商品列表
在电商领域,根据关键词获取商品列表是常见的需求。某手作为国内知名的电商平台,提供了丰富的商品资源。通过 Java 爬虫技术,我们可以高效地根据关键词获取某手商品列表,并提取商品的基本信息。本文将详细介绍如何利用 Java 爬虫根…...
Axure项目实战:智慧运输平台后台管理端-订单管理2(多级交互)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:订单管理2 主要内容:中继器筛选、表单跟随菜单拖动、审批数据互通等 应用场景:订单管理…...

篇章五 项目创建
目录 1.创建一个SpringBoot项目 2.创建核心类 2.1 Exchange类 2.2 MessageQueue类 2.3 Binding类 2.4 Message类 1.Message的组成 2.逻辑删除 3.工厂方法 4.序列化与反序列化 5.offsetBeg和offsetEnd 1.创建一个SpringBoot项目 1.点击 2.填写表单 3.添加依赖 2.创建…...
Ntfs!ATTRIBUTE_RECORD_HEADER结构$INDEX_ROOT=0x90的一个例子
Ntfs!ATTRIBUTE_RECORD_HEADER结构$INDEX_ROOT0x90的一个例子 1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_FILE_RECORD_SEGMENT_HEADER *)0xc431a400) ((Ntfs!_FILE_RECORD_SEGMENT_HEADER *)0xc431a400) : 0xc431a400 [Type: _FILE_RECORD_SEGMENT_HEADER …...