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 102.计数器文章浏览量incr article:9527:view3.Token存储用户登录态List-ziplist元素少且值小连续内存节省空间。-linkedlist元素多双向链表方便两端操作。项目实战1.消息队列LPUSHBRPOP实现生产者-消费者。2.最新动态LPUSH user:1001:newsLTRIM保留前100条。Hash-ziplist字段少且值小。-hashtable字段多哈希表链地址法解决冲突。项目实战1.对象缓存存储用户信息hmset user:1001 name 张三 age 252.购物车hincrby cart:1001 article:2001 1Set-intset整数且少有序无重复整数数组二分查找。-hashtable非整数或多元素作键值为NULL。项目实战1.共同好友sinter user:1001:friends user:1002:friends2.抽奖去重sadd lottery:2024 useridZSet-ziplist元素少且值小。-skiplist hashtable跳跃表保证有序哈希表快速查分值。项目实战1.排行榜zadd rank:day:20240301 100 user12.延迟队列时间戳作为scorezrangebyscore拉取到期任务2. Redis常用的命令有哪些通用keys生产禁用、scan推荐、expire、ttl、delStringset、get、incr、setnx、msetHashhset、hget、hgetall、hincrbyListlpush、rpop、brpop、lrangeSetsadd、smembers、sinter、sunionZSetzadd、zrange、zrevrange、zscore二、持久化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多路复用模型非阻塞IO2. 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. 哨兵模式工作流程主观下线单个哨兵发现节点无响应。客观下线多个哨兵quorum都认为主节点下线。选举领头哨兵基于Raft算法选出一个执行故障转移。故障转移从从库中选一个新主库优先级 复制偏移量 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. 布隆过滤器误判怎么办背景布隆过滤器判断不存在一定准确判断存在可能误判。解决方案容忍业务允许少量误判如推荐系统。兜底即使布隆说过存在查DB没数据按穿透处理缓存空值。定期重建定时从DB重新构建布隆过滤器。七、数据一致性1. Redis和MySQL数据一致性如何保证常见方案对比方案原理优点缺点旁路缓存读先查缓存没有查DB并回写。写先更新DB再删缓存。简单适合读多写少。删除缓存可能失败需重试。读写穿透缓存层封装DB操作应用只操作缓存。应用逻辑简单。缓存层复杂实现难度大。异步消息更新DB后发消息消费者更新缓存。解耦最终一致。消息可能丢失或重复。Canal监听binlog监听MySQL binlog变更异步更新缓存。与业务代码解耦可靠。引入Canal组件复杂度高。2. 项目实战先更新DB还是先删缓存经典问题先删缓存再更新DB可能导致脏数据。缓存更新策略:旁路缓存读时先查 Redis无则查 MySQL 并更新 Redis写时先更新 MySQL再删 Redis缓存。延迟双删策略,更新完数据库后删除缓存,休眠一小会儿-几百毫秒,再删一次缓存。(原因:线程1更新数据库的瞬间,线程2查询到了旧数据,然后线程1删除缓存,此时网络延迟线程2把查询到的旧数据写到缓存里面了,导致读取到旧数据)读写穿透读、写操作由缓存处理缓存负责和数据库同步。异步缓存写入写操作直接更新 RedisRedis 异步更新到 MySQL。消息队列更新 MySQL 时发消息到队列消费者据此更新 Redis实现最终一致。分布式事务如两阶段提交协调者让参与者准备和提交补偿事务TCC分尝试、确认、取消阶段。定期同步用定时任务定期从 MySQL 取数据更新到 Redis八、分布式锁与项目实战1. Redis分布式锁实现原理使用场景:定时任务操作数据库,是多实例的,所以需要使用到分布式锁大模型问答的时候,同一个用户问答流式回答过程中,不能开启两个页面去问答,使用到了分布式锁使用流程用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. 项目实战分布式锁使用场景(问答)
Java面试-08-分布式缓存Redis
发布时间:2026/6/27 6:06:40
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 102.计数器文章浏览量incr article:9527:view3.Token存储用户登录态List-ziplist元素少且值小连续内存节省空间。-linkedlist元素多双向链表方便两端操作。项目实战1.消息队列LPUSHBRPOP实现生产者-消费者。2.最新动态LPUSH user:1001:newsLTRIM保留前100条。Hash-ziplist字段少且值小。-hashtable字段多哈希表链地址法解决冲突。项目实战1.对象缓存存储用户信息hmset user:1001 name 张三 age 252.购物车hincrby cart:1001 article:2001 1Set-intset整数且少有序无重复整数数组二分查找。-hashtable非整数或多元素作键值为NULL。项目实战1.共同好友sinter user:1001:friends user:1002:friends2.抽奖去重sadd lottery:2024 useridZSet-ziplist元素少且值小。-skiplist hashtable跳跃表保证有序哈希表快速查分值。项目实战1.排行榜zadd rank:day:20240301 100 user12.延迟队列时间戳作为scorezrangebyscore拉取到期任务2. Redis常用的命令有哪些通用keys生产禁用、scan推荐、expire、ttl、delStringset、get、incr、setnx、msetHashhset、hget、hgetall、hincrbyListlpush、rpop、brpop、lrangeSetsadd、smembers、sinter、sunionZSetzadd、zrange、zrevrange、zscore二、持久化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多路复用模型非阻塞IO2. 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. 哨兵模式工作流程主观下线单个哨兵发现节点无响应。客观下线多个哨兵quorum都认为主节点下线。选举领头哨兵基于Raft算法选出一个执行故障转移。故障转移从从库中选一个新主库优先级 复制偏移量 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. 布隆过滤器误判怎么办背景布隆过滤器判断不存在一定准确判断存在可能误判。解决方案容忍业务允许少量误判如推荐系统。兜底即使布隆说过存在查DB没数据按穿透处理缓存空值。定期重建定时从DB重新构建布隆过滤器。七、数据一致性1. Redis和MySQL数据一致性如何保证常见方案对比方案原理优点缺点旁路缓存读先查缓存没有查DB并回写。写先更新DB再删缓存。简单适合读多写少。删除缓存可能失败需重试。读写穿透缓存层封装DB操作应用只操作缓存。应用逻辑简单。缓存层复杂实现难度大。异步消息更新DB后发消息消费者更新缓存。解耦最终一致。消息可能丢失或重复。Canal监听binlog监听MySQL binlog变更异步更新缓存。与业务代码解耦可靠。引入Canal组件复杂度高。2. 项目实战先更新DB还是先删缓存经典问题先删缓存再更新DB可能导致脏数据。缓存更新策略:旁路缓存读时先查 Redis无则查 MySQL 并更新 Redis写时先更新 MySQL再删 Redis缓存。延迟双删策略,更新完数据库后删除缓存,休眠一小会儿-几百毫秒,再删一次缓存。(原因:线程1更新数据库的瞬间,线程2查询到了旧数据,然后线程1删除缓存,此时网络延迟线程2把查询到的旧数据写到缓存里面了,导致读取到旧数据)读写穿透读、写操作由缓存处理缓存负责和数据库同步。异步缓存写入写操作直接更新 RedisRedis 异步更新到 MySQL。消息队列更新 MySQL 时发消息到队列消费者据此更新 Redis实现最终一致。分布式事务如两阶段提交协调者让参与者准备和提交补偿事务TCC分尝试、确认、取消阶段。定期同步用定时任务定期从 MySQL 取数据更新到 Redis八、分布式锁与项目实战1. Redis分布式锁实现原理使用场景:定时任务操作数据库,是多实例的,所以需要使用到分布式锁大模型问答的时候,同一个用户问答流式回答过程中,不能开启两个页面去问答,使用到了分布式锁使用流程用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. 项目实战分布式锁使用场景(问答)