当前位置: 首页 > news >正文

Java面试-08-分布式缓存Redis

Redis 面试题汇总

目录

  • 一、基础与数据类型
    • 1. Redis有哪些数据类型?底层实现和应用场景是什么?
    • 2. Redis常用的命令有哪些?
  • 二、持久化
    • 1. Redis提供了哪几种持久化方式?如何选择?
  • 三、高性能与线程模型
    • 1. Redis为什么快?
    • 2. Redis为什么是单线程的?现在还是单线程吗?
  • 四、Redis事务
    • 1. Redis事务的ACID特性
    • 2. Redis事务的常用命令
    • 3. Redis事务的实现原理
    • 4. Redis事务与数据库事务的区别
    • 5. Redis事务的适用场景
  • 五、高可用与集群
    • 1. Redis集群方案有哪些?
    • 2. 哨兵模式工作流程
    • 3. Redis Cluster哈希槽原理
  • 六、缓存常见问题
    • 1. 缓存穿透、击穿、雪崩的区别与解决方案
    • 2. 布隆过滤器误判怎么办?
    • 3. 互斥锁方案下,其他线程等待多久?
  • 七、数据一致性
    • 1. Redis和MySQL数据一致性如何保证?
    • 2. 项目实战:先更新DB还是先删缓存?
    • 3. 最终一致还是强一致?
  • 八、分布式锁与项目实战
    • 1. Redis分布式锁实现原理
    • 2. 可能出现的问题及解决方案
    • 3. RedLock算法的争议
    • 4. 可重入锁实现
    • 5. 看门狗机制
    • 6. 项目实战:军用多模态检索系统数据更新

一、基础与数据类型

1. Redis有哪些数据类型?底层实现和应用场景是什么?

数据类型底层实现项目实战场景
String简单动态字符串(SDS)。
-embstr(短字符串):SDS和RedisObject连续存储,省内存。
-raw(长字符串):两者分开存储。
项目实战
1.分布式锁set article:1001:lock uuid nx ex 10
2.计数器:文章浏览量incr article:9527:view
3.Token存储:用户登录态
List-ziplist(元素少且值小):连续内存,节省空间。
-linkedlist(元素多):双向链表,方便两端操作。
项目实战
1.消息队列LPUSH+BRPOP实现生产者-消费者。
2.最新动态LPUSH user:1001:news+LTRIM保留前100条。
Hash-ziplist(字段少且值小)。
-hashtable(字段多):哈希表,链地址法解决冲突。
项目实战
1.对象缓存:存储用户信息hmset user:1001 name "张三" age 25
2.购物车hincrby cart:1001 article:2001 1
Set-intset(整数且少):有序无重复整数数组,二分查找。
-hashtable(非整数或多):元素作键,值为NULL。
项目实战
1.共同好友sinter user:1001:friends user:1002:friends
2.抽奖去重sadd lottery:2024 userid
ZSet-ziplist(元素少且值小)。
-skiplist + hashtable:跳跃表保证有序,哈希表快速查分值。
项目实战
1.排行榜zadd rank:day:20240301 100 user1
2.延迟队列:时间戳作为score,zrangebyscore拉取到期任务

2. Redis常用的命令有哪些?

  • 通用keys(生产禁用)、scan(推荐)、expirettldel
  • Stringsetgetincrsetnxmset
  • Hashhsethgethgetallhincrby
  • Listlpushrpopbrpoplrange
  • Setsaddsmemberssintersunion
  • ZSetzaddzrangezrevrangezscore

二、持久化

1. Redis提供了哪几种持久化方式?如何选择?

RDB(快照)
  • 原理:每隔一段时间,将内存中的数据集写到磁盘Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程不进行任何IO操作
  • 保存策略save(同步阻塞)、bgsave(异步)、配置文件自动触发。save x x 几秒内有几个key的变化就触发
  • 优点:文件紧凑,恢复快,对主进程性能影响小。
  • 缺点:可能丢失最后一次快照后的数据。
AOF(追加文件)
  • 原理:以日志形式记录每个写操作,重启时重放。
  • 刷盘策略
    • always:每次写命令都同步,最安全,性能最差
    • everysec:每秒同步,最多丢1秒数据(默认推荐)
    • no:由操作系统决定,性能最好,最不安全
  • 优点:数据安全性高。
  • 缺点:文件大,恢复慢,IO压力大。
混合持久化
  • 原理:RDB做全量快照 + AOF做增量日志。
  • 优势:结合两者优点,重启加载RDB快,数据丢失少。
生产环境选择策略
  • 方案一(推荐)RDB + AOF混合持久化。RDB做冷备和快速恢复,AOF保证数据可靠性。
  • 方案二(缓存场景):完全关闭持久化,只做内存缓存,性能最高。
  • 方案三(主从架构):主库关闭持久化(避免fork影响性能),从库开启AOF。

三、高性能与线程模型

1. Redis为什么快?

  • 内存操作:基于内存操作,读写快。
  • 单线程模型:避免多线程的锁竞争,保证操作原子性。
  • 数据结构简单:对数据操作也简单。使用底层模型不同:
  • 构建了自己的VM 机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求
  • I/O 多路复用:使用I/O多路复用模型,非阻塞IO

2. Redis为什么是单线程的?现在还是单线程吗?

核心澄清

  • Redis的命令执行仍然是单线程的。
  • Redis 6.0+ 引入了多线程IO,用于网络数据的读写和解析,但命令执行依然是单线程。

为什么命令执行保持单线程?

  • 避免锁竞争,简化数据结构和逻辑。
  • 瓶颈通常不在CPU,而在内存和网络IO。
  • 多线程IO解决了网络吞吐的瓶颈。

多线程IO配置

io-threads 4 # 开启4个IO线程 io-threads-do-reads yes # 开启读线程

四、Redis事务

1. Redis事务的ACID特性

Redis事务的ACID特性与传统数据库事务的区别

核心结论:Redis事务不是严格意义上的ACID事务,它更像是一个批量执行命令的机制

2. Redis事务的实现原理

事务队列

  • 执行MULTI后,Redis会将后续的命令放入一个队列中,不立即执行。
  • 命令入队时,Redis会检查语法错误,如果有语法错误,会立即返回错误。
  • 语法正确的命令会被放入队列,等待EXEC执行。

命令执行

  • 执行EXEC时,Redis会按顺序执行队列中的所有命令。
  • 执行过程中,如果某个命令执行失败(如对非字符串类型执行INCR),后续命令仍会继续执行。
  • EXEC返回所有命令的执行结果,包括错误信息。

WATCH机制的实现

  • WATCH命令会将key标记为"被监视"。
  • 在EXEC执行前,Redis会检查被监视的key是否被修改。
  • 如果被修改,EXEC会返回nil,事务执行失败。
  • 如果未被修改,EXEC正常执行,并清除所有监视标记。

5. Redis事务的适用场景

五、高可用与集群

1. Redis集群方案有哪些?

方案原理优点缺点
主从复制一主多从,从库同步主库数据。读写分离,读扩展,数据备份。手动故障转移,写单点。
哨兵模式在主从基础上加监控、通知、自动故障转移。高可用,自动主从切换。写单点,数据量受单机内存限制。
Redis Cluster去中心化,数据分片(16384个槽),每个节点负责一部分槽。分布式,线性扩展,自动故障转移。架构复杂,跨节点操作受限。

2. 哨兵模式工作流程

  1. 主观下线:单个哨兵发现节点无响应。
  2. 客观下线:多个哨兵(>=quorum)都认为主节点下线。
  3. 选举领头哨兵:基于Raft算法选出一个执行故障转移。
  4. 故障转移
  • 从从库中选一个新主库(优先级 > 复制偏移量 > runid)
  • 其他从库指向新主库
  • 通知客户端

3. Redis Cluster哈希槽原理

  • 集群有16384个哈希槽
  • key通过 CRC16(key) % 16384 计算属于哪个槽。
  • 每个节点负责一段连续的槽范围(如 0-5000)。
  • 槽是数据迁移和负载均衡的基本单位。

为什么不使用一致性哈希?

哈希槽简化了数据分布和迁移的实现,节点增减只需迁移部分槽,不用全部重新哈希。


六、缓存常见问题

1. 缓存穿透、击穿、雪崩的区别与解决方案

问题现象原因解决方案
缓存穿透请求数据在缓存和DB都不存在,每次都打到DB。恶意攻击(查不存在的ID)。1.布隆过滤器:拦截不存在请求。
2.缓存空值:key-null,短过期时间。
缓存击穿热点key过期瞬间,大量请求打到DB。热点key过期 + 高并发。1.永不过期:后台更新。
2.互斥锁:只让一个线程查DB更新缓存。
缓存雪崩大量key同时过期,或Redis宕机,DB被打垮。集中过期/缓存故障。1.过期时间加随机值
2.集群高可用
3.限流降级

2. 布隆过滤器误判怎么办?

背景:布隆过滤器判断"不存在"一定准确,判断"存在"可能误判。

解决方案

  1. 容忍:业务允许少量误判(如推荐系统)。
  2. 兜底:即使布隆说过"存在",查DB没数据,按穿透处理(缓存空值)。
  3. 定期重建:定时从DB重新构建布隆过滤器。

七、数据一致性

1. Redis和MySQL数据一致性如何保证?

常见方案对比

方案原理优点缺点
旁路缓存读:先查缓存,没有查DB并回写。
写:先更新DB,再删缓存。
简单,适合读多写少。删除缓存可能失败,需重试。
读写穿透缓存层封装DB操作,应用只操作缓存。应用逻辑简单。缓存层复杂,实现难度大。
异步消息更新DB后发消息,消费者更新缓存。解耦,最终一致。消息可能丢失或重复。
Canal监听binlog监听MySQL binlog变更,异步更新缓存。与业务代码解耦,可靠。引入Canal组件,复杂度高。

2. 项目实战:先更新DB还是先删缓存?

经典问题:先删缓存再更新DB,可能导致脏数据。

缓存更新策略:

  1. 旁路缓存:读时先查 Redis,无则查 MySQL 并更新 Redis;写时先更新 MySQL,再删 Redis缓存。
  • 延迟双删策略,更新完数据库后删除缓存,休眠一小会儿-几百毫秒,再删一次缓存。(原因:线程1更新数据库的瞬间,线程2查询到了旧数据,然后线程1删除缓存,此时网络延迟线程2把查询到的旧数据写到缓存里面了,导致读取到旧数据)
  1. 读写穿透:读、写操作由缓存处理,缓存负责和数据库同步。异步缓存写入:写操作直接更新 Redis,Redis 异步更新到 MySQL。
  2. 消息队列:更新 MySQL 时发消息到队列,消费者据此更新 Redis,实现最终一致。
  3. 分布式事务:如两阶段提交,协调者让参与者准备和提交;补偿事务(TCC)分尝试、确认、取消阶段。
  4. 定期同步:用定时任务定期从 MySQL 取数据更新到 Redis

八、分布式锁与项目实战

1. Redis分布式锁实现原理

使用场景:

  1. 定时任务操作数据库,是多实例的,所以需要使用到分布式锁

  2. 大模型问答的时候,同一个用户问答流式回答过程中,不能开启两个页面去问答,使用到了分布式锁

  3. 使用流程

    • 用set nx ex 原子命令加锁,key是锁的唯一键(可以使用业务:方法:唯一值),value是线程id,执行成功说明获取到了锁,可以执行业务
    • 在finally里面使用lua脚本校验线程id是否一致,然后再释放锁
  • 问题1:死锁问题:业务代码崩溃,长时间不释放锁,导致死锁
    • 解决:加上过期时间
  • 问题2:锁误释放问题:A线程获取到了锁,但是执行时间比较长,导致锁过期了,B线程获取到了锁,此时A线程执行完了要释放锁,却把B的锁释放了
    • 解决:给每个锁设置唯一标识,在finally里面使用lua脚本校验线程id是否一致,然后再释放锁
  • 问题3:锁过期导致并发问题:业务还没执行完,锁被释放,导致并发问题
    • 解决:使用redission的看门狗机制,锁会自动续期,30秒
  • 问题4:集群下数据一致性问题:主从复制延迟,导致锁失效
    • 解决:使用redission的红锁算法,客户端向一半以上的节点获取锁,获取到了说明成功,释放的时候向所有节点释放锁

2. 看门狗机制

作用:业务执行时间可能超过锁过期时间,自动续期。

实现思路

  • 获取锁成功后,启动一个守护线程。
  • 每隔 1/3 过期时间(如过期10秒,每3秒检查一次),如果任务还在执行,就续期。
  • Redisson框架已实现此机制。

3. 项目实战:分布式锁使用场景(问答)

http://www.cnnetsun.cn/news/3027729.html

相关文章:

  • 矢量网络分析仪测量实用指南
  • 轻养新风席卷中秋 鲜品屋2026新品发布会圆满举办
  • 厦门市铧大技术学校打造“AI+”全专业职教新高地
  • 2026年免漆吸塑厂家选择指南:这3点最关键
  • 工装采购如何筛选靠谱厂商
  • 探索光伏储能技术,哪种方案更稳定可靠?
  • CAXA电子图版安装步骤(附安装包)CAXA电子图版2024 超详细下载安装教程
  • 【课程设计/毕业设计】基于 SpringBoot+Vue 的高校师生教学评价服务系统的设计与实现【附源码、数据库、万字文档】
  • HDR图像高斯双边滤波MATLAB实现
  • AI率太高怎么降?10款降AI率软件实测(含免费降ai率工具)真实避坑指南
  • 巯基化海藻酸钠(SH-Alg)水凝胶与琼脂糖(Agarose)凝胶的应用差异
  • RAG:让大模型“开卷考试“的神器,三步搞定知识更新!
  • 什么是 NGINX 日志?
  • XR 无限空间项目案例:从场地规划到现场安装全流程
  • AI 音频平台引入谷歌隐形水印技术,未来几周将覆盖所有音频生成内容
  • 2026零基础语音转文字总结使用场景避坑指南 包教包会可直接上手
  • Seed与Root在密码学中的区别
  • 提高脂质体维生素利用率的关键因素是什么?(科普解析)
  • 户外 4G 报警器方案设计:MP3 录音 + LBS 定位 + 低功耗待机
  • claude目前具备以下技能:
  • 30VOUT,2A,XZ5100,升压LED恒流驱动芯片
  • 互联网医院预约接单微信小程序搭建软件系统开发
  • 工业级AIGC视频重塑汽车广告生态:集之互动以高可控技术实现降本增效
  • 4 种 PS 证件照换底色方法|白底快速换成标准蓝底
  • D3.js 完整详细使用教程(从入门到实战)
  • ScaleTail:自托管服务一键接入 Tailscale 网络
  • OpenAI芯片Jalapeño亮相,能否打破英伟达算力垄断?
  • 自己开店怎么弄扫码点餐,扫码点餐小程序,门店盈利翻倍的秘密武器
  • 基点起源半年订单金额升一级,工业AI系统为传统行业提质增效、降本千万!
  • AI 能力溢出,人成瓶颈!深度解析写代码与网关重写中的技术变革与决策挑战