)
适用岗位Java 后端覆盖底层、持久化、集群、缓存问题贴合你岗位要求1.Redis 基础(1).Redis 是什么特点一、定义Redis 是内存型 KV 数据库基于 C 语言开发单线程模型IO 多路复用。Redis 是C 语言编写、基于内存的高性能 Key-Value 非关系型数据库常用来做缓存也可用于分布式锁、限流、消息队列、计数器等场景。二、核心特点⭐背诵要点1.高性能数据存内存采用 IO 多路复用命令执行单线程避免多线程锁竞争与上下文切换读写性能很高。补充命令执行单线程持久化、异步删除、网络监听等有独立后台线程不是整个 Redis 只有一个线程。2.丰富的数据类型原生支持多种结构String、List、Hash、Set、ZSet能满足不同业务场景不仅仅只能存简单字符串。3.支持持久化提供 RDB、AOF 两种持久化方案可以把内存数据落盘重启后数据恢复防止断电丢失数据。4.高可用、分布式能力支持主从复制、哨兵 Sentinel、Redis Cluster 分片集群实现读写分离、故障自动转移、水平扩容。5.其他能力支持 Lua 脚本保证多条命令原子执行支持发布订阅支持事务不支持回滚支持过期键自动删除、内存淘汰策略支持管道 Pipeline 批量命令降低网络 RTT。三、高频深挖面试题Q1Redis 单线程为什么还这么快绝大部分操作是内存操作IO 多路复用 epoll单线程监听大量连接避免多线程锁竞争、CPU 上下文切换开销Redis 通信协议简单解析成本低。Q2Redis 和 Memcached 区别Redis 支持多数据结构Memcached 只支持简单 key-valueRedis 支持持久化Memcached 不持久化Redis 支持集群Memcached 分布式靠客户端Redis 单线程Memcached 多线程。Q3Redis 除了缓存还有哪些业务用途分布式锁、接口限流、计数器、排行榜ZSet、会话存储、消息队列、布隆过滤器。一句话背诵总结Redis 是 C 语言开发的内存 KV 数据库高性能、多数据结构、支持 RDB/AOF 持久化支持主从、哨兵、集群附带 Lua、发布订阅、事务等能力常用于缓存、分布式锁、限流等场景。(2).Redis 单线程模型为什么快一、Redis 单线程模型重点Redis 处理命令是单线程不是 Redis 整个进程只有一个线程。Redis 核心事件循环线程负责接收网络连接、解析命令、执行读写命令所有客户端命令串行执行。其他任务由独立后台线程处理RDB/AOF 持久化bigkey 异步删除unlink文件刷盘集群心跳等底层采用IO 多路复用 epoll。一个线程监听多个 socket 连接不用为每个连接创建线程。所有命令排队执行天然避免命令执行阶段的并发竞争不需要锁。误区纠正单线程只是命令执行模块不是全部功能单线程。二、Redis 为什么速度很快⭐背诵 4 点数据存在内存内存访问速度远大于磁盘没有磁盘 IO 开销。IO 多路复用 epoll单线程监听大量客户端 socket以少量线程处理上万连接减少线程创建销毁、上下文切换。避免多线程锁竞争、上下文切换命令串行执行不需要加锁省去锁等待和 CPU 上下文切换开销。协议简单编码高效RESP 简单文本协议解析开销低C 语言实现底层内存操作高效。三、高频深挖面试题Q1单线程会不会 CPU 瓶颈会。如果执行慢命令keys、hgetall、大量 Lua阻塞事件循环所有客户端请求等待。生产禁止线上执行 keys用 scan 替代。Q2IO 多路复用是什么一个线程监听多个文件描述符socket内核告诉线程哪些 socket 就绪可读 / 可写线程只处理就绪连接不用轮询。Linux 下是 epollwindows select。Q3Redis 单线程多客户端并发请求怎么处理客户端请求全部进入内核缓冲区redis 事件循环依次读取、排队串行执行。一个命令执行完再处理下一个。Q4单线程模型优缺点优点无锁实现简单没有多线程竞争、上下文切换。 缺点一条慢命令阻塞整个线程多核机器不能直接利用多核 CPU。解决方案Redis6 引入多线程 IO命令执行依旧单线程。Q5Redis6 多线程做了什么Redis6 的多线程只用于网络 IO 读写命令执行依旧是单线程不改变核心执行模型用来提升网络 IO 性能。一句话背诵总结Redis 命令执行是单线程底层 epoll IO 多路复用之所以快内存存储、IO 多路复用、无锁无上下文切换、协议简单慢命令会阻塞主线程Redis6 多线程仅用于网络 IO命令执行仍然单线程。2. 5 大基础数据结构高频重点是对外的数据结构每一种都有多种底层编码Redis 自动选择节省内存。(1).String 字符串常用命令set、get、incr、decr、append、setnx底层SDS 简单动态字符串SDS 特点记录 len获取字符串长度 O (1)二进制安全可以存图片、字节数组预分配内存减少频繁扩容防止缓冲区溢出适用场景计数器、分布式锁、简单缓存、session 存储。(2).List 列表常用命令lpush、rpush、lpop、rpop、lrange底层Redis3.2 之后统一为quicklist快速链表quicklist 双向链表链表的每个节点是 ziplist 压缩列表。特点头尾操作 O (1)中间查找 O (n)。适用场景消息队列、排行榜、最新消息列表。(3).Hash 哈希常用命令hset、hget、hgetall、hmget底层数据量小时 ziplist数据量大转 hashtable特点适合存储对象一个 key 存放多个 field-value。适用场景用户信息、商品信息局部更新字段不用序列化整个对象。(4).Set 集合常用命令sadd、smembers、sismember、sinter 交集底层hashtable字典元素无序、不可重复特点自动去重支持交集、并集、差集运算。适用场景好友关系、去重、抽奖、标签。(5).ZSet 有序集合常用命令zadd、zrange、zrank、zrem底层少量数据 ziplist大数据skiplist 跳表 字典skiplist多层索引链表O (logn) 查找插入实现有序dict 字典保证元素唯一快速查找 member 特点元素不可重复按 score 分值排序。 适用场景排行榜、延时队列、限流。高频深挖面试题Q1ziplist 什么时候转为 hashtable/skiplist两个阈值元素数量超过阈值或者单个元素长度超过阈值自动转换。目的平衡内存和性能。Q2跳表为什么不用红黑树跳表插入删除简单范围查询友好红黑树需要复杂旋转操作CPU 开销更高。Redis 需要频繁范围遍历选跳表。Q3Hash 和 String 存对象怎么选对象字段经常局部更新 → Hash对象整体读取、几乎不变 → String 序列化。Q4List 可以做消息队列为什么不推荐生产用没有消息确认 ACK消息丢失风险无法多消费组消息堆积性能差。生产推荐专业 MQ。Q5SDS 和 C 原生字符串区别C 字符串以\0结尾不能存二进制获取长度遍历计算 O (n)。SDS 单独存长度二进制安全O (1) 获取长度。一句话背诵总结String 底层 SDSList 是 quicklistHash、Set 底层 ziplist/hashtableZSet 底层跳表 字典ziplist 适合少量数据量大自动切换ZSet 适合排行榜。(6).SDS 简单动态字符串优点记录长度获取长度 O (1)预分配空间减少扩容杜绝 C 语言缓冲区溢出二进制安全可存图片、字节流。3.Redis 持久化 RDB AOPAOF持久化作用内存数据落磁盘Redis 宕机重启后恢复数据两种持久化可同时开启。一、RDBRedis DataBase快照1.原理在某个时间点把内存中全量数据生成二进制快照文件 dump.rdb。2.触发方式save主线程执行阻塞 Redis生产不推荐。bgsave常用fork 子进程子进程负责写 RDB 文件主进程继续处理客户端请求。配置自动触发redis.conf 里 save 900 1 等规则主从同步时也会触发 bgsave。优点文件是二进制体积小重启恢复速度快适合冷备份。缺点存在丢数据风险两次快照之间新增的数据宕机会丢失。fork 子进程时大内存实例拷贝页表会短暂消耗 CPU 内存。二、AOFAppend Only File追加日志1.原理记录每一条写命令追加写入 aof 日志文件重启时重新执行命令恢复数据。2.刷盘策略appendfsyncalways每次写命令都刷磁盘最安全性能最差。everysec默认每秒刷一次最多丢失 1 秒数据平衡安全和性能。no交给操作系统决定刷盘时机性能高丢数据不可控。AOF 重写bgrewriteaof AOF 文件不断变大后台子进程把内存当前状态生成精简 AOF 文件合并冗余命令压缩文件。重写不读取旧 aof直接读内存数据。优点数据安全性更高丢失数据更少。缺点文件体积比 RDB 大数据恢复速度慢。三、RDB vs AOF 对比RDB二进制快照恢复快文件小会丢失一段时间数据适合备份。AOF命令日志数据更安全文件大恢复慢。生产环境同时开启 RDBAOF重启优先加载 AOFAOF 损坏时可以用 RDB 兜底。高频深挖面试题Q1bgsave 的 fork 会阻塞 Redis 吗fork 过程短暂阻塞主线程拷贝页表fork 完成后子进程写文件主进程不阻塞。Redis 内存越大fork 耗时越长。Q2AOF 重写会阻塞主线程吗重写由子进程执行不会阻塞主线程重写期间新命令同时写入旧 AOF 和重写缓冲区。Q3为什么重启优先加载 AOFAOF 保存的数据更新丢失更少优先级更高。Q4可以只开 RDB 吗可以但宕机可能丢失大量数据对数据一致性要求高的业务不推荐。一句话背诵总结RDB 是二进制快照bgsave fork 子进程恢复快但可能丢数据AOF 记录写命令everysec 每秒刷盘数据更安全AOF 文件过大触发后台重写生产同时开启重启优先加载 AOF。4.缓存三大经典问题【最高频】一句话区分记忆穿透查不存在的数据击穿热点 key 过期雪崩大量 key 同时过期(1)缓存穿透定义查询数据库根本不存在的数据缓存里也没有请求直接打到数据库。大量请求会压垮 DB。例子查 id-1不存在的商品编号。解决方案缓存空值查询 DB 为空向 Redis 存入空值设置较短过期时间。布隆过滤器前置拦截把所有合法 id 预加载进布隆过滤器不存在的数据直接拦截不去查缓存和 DB。参数校验接口层做参数合法性校验。(2)缓存击穿定义单个热点 key 过期高并发瞬间大量请求绕过缓存直接访问数据库。 例子秒杀商品商品缓存刚好过期上万请求打到 DB。解决方案互斥锁Redis 分布式锁只放一个请求去更新缓存其他请求等待Redisson。逻辑过期key 永不过期在 value 里存过期时间后台异步更新缓存不删除 key。(3)缓存雪崩定义大批量缓存 key 同时过期大量请求同时打到数据库数据库压力骤增服务瘫痪。补充还有一种雪崩场景Redis 服务宕机所有缓存全部失效。解决方案过期时间加随机值打散过期时间避免同一时刻大量 key 失效。Redis 集群高可用主从 哨兵 / Cluster防止 Redis 单点故障。服务层限流、熔断降级保护数据库。多级缓存本地 Caffeine 缓存 Redis减少 Redis 压力。高频深挖面试题Q1缓存空值有什么缺点会占用 Redis 内存如果不存在的 key 很多会存大量空 key。适合少量非法查询场景海量不存在 key 优先布隆过滤器。Q2逻辑过期的缺点数据存在短暂不一致需要后台线程异步刷新缓存。Q3互斥锁方案缺点并发高时会产生等待存在少量性能损耗可能出现死锁需要设置锁超时。Q4雪崩和击穿区别击穿是单个热点 key过期雪崩是大量 key 集体失效。Q5Redis 宕机引发的雪崩怎么处理依靠集群高可用同时限流熔断开启本地缓存兜底。一句话背诵总结穿透查不存在数据方案缓存空值、布隆过滤器击穿热点 key 过期互斥锁 / 逻辑过期雪崩大量 key 同时失效随机过期时间、集群高可用、限流熔断。5.过期 key 删除策略一、过期 key 删除策略3 种策略配合使用Redis 不会在 key 过期瞬间立刻删除实时删除开销太大采用组合策略。1.惰性删除被动删除访问 key 的时候才判断是否过期过期则删除返回 nil。优点节省 CPU只处理用到的 key。缺点如果 key 一直不访问就算过期也一直占内存内存浪费。2.定期删除主动采样删除Redis 后台线程每隔一段时间随机抽取一批设置了过期的 key检查并删除过期 key。不是遍历所有 key只是采样避免阻塞主线程。间隔默认 100ms 执行一次。 优点弥补惰性删除的内存浪费。 缺点采样是随机的部分过期 key 依然残留。上面两种只是清理过期 key当 Redis 内存达到 maxmemory 上限时触发内存淘汰策略。二、内存淘汰策略maxmemory-policy共 8 种前提redis.conf 配置 maxmemory限定 Redis 最大可用内存内存满之后执行淘汰。allkeys-lru生产最常用所有 key优先淘汰最近最少使用的 key。volatile-lru 只在设置了过期时间的 key 里面淘汰最近最少使用。allkeys-lfu 所有 key淘汰使用频率最低的 key。volatile-lfu 仅过期 key 集合内淘汰使用频率最低。allkeys-random 全部 key 中随机删除。volatile-random 在带过期 key 里随机删。volatile-ttl 挑选快要到期的 key 优先删除。noevictionRedis 默认策略内存满了不删除任何 key直接返回 OOM 错误拒绝写入。LRU最近最少使用LFU使用频次最低。Redis 并不是严格 LRU是近似 LRU节约内存。高频深挖面试题Q1惰性 定期删除还删不完过期 key 怎么办内存达到 maxmemory 上限触发内存淘汰策略。Q2volatile 和 allkeys 前缀区别volatile只看带有过期时间的 keyallkeysRedis 里全部 key不管有没有过期时间。Q3近似 LRU 原理Redis 不会维护完整 LRU 链表耗内存每个 key 保存 24bit 的 LRU 时钟采样对比近似实现 LRU节省性能。Q4什么时候会触发内存淘汰执行写命令set、hset 等时Redis 检查内存占用如果超出 maxmemory执行淘汰。读命令不会触发。Q5LFU 相比 LRU 优势LRU 只看最近访问时间LFU 看访问频次。适合淘汰很久不访问但偶尔被访问的冷数据。一句话背诵总结过期 key惰性删除访问才删 定期随机采样删除内存满触发 8 种淘汰策略生产推荐 allkeys-lrunoeviction 默认内存满直接报错拒绝写入。6.分布式锁核心分布式锁目的是多服务实例竞争同一资源保证同一时刻只有一个线程执行业务。一、原生 Redis 实现分布式锁SET NX EX(1)旧方案缺陷setnx expiresetnx key value expire key 30两条独立命令非原子。setnx 成功后服务宕机expire 没执行锁永久存在死锁。(2)正确单命令原子写法SET lock 1 NX EX 30NXkey 不存在才创建EX设置过期时间。一条命令原子加锁解决死锁问题。(3)原生 SET NX EX 仍然存在 3 大问题锁过期业务还没执行完锁超时释放其他线程拿到锁前面线程执行完误删除别人的锁。解锁非原子判断锁是自己的 删除两条命令并发下会误删别人锁。 ✅ 解决Lua 脚本解锁保证判断 删除原子执行value 存线程标识。主从切换锁失效主节点加锁成功还没同步到从节点主宕机从升级为主其他客户端再次获取锁锁失效Redlock 解决生产很少用。二、Redisson生产推荐⭐核心原理基于 Lua 脚本实现加锁、解锁原子操作看门狗 Watchdog 自动续期。(1)看门狗默认锁超时 30s业务线程持有锁未执行完毕后台看门狗线程每 10s 自动延长锁过期时间业务执行完成主动释放锁停止续期业务宕机锁到期自动释放。(2)可重入锁同一个线程可以多次加锁内部维护锁计数器加锁 1解锁 - 1计数器为 0 才释放锁。(3)锁释放Lua 脚本校验锁归属计数器减到 0 删除 key。Redisson 锁种类RLock 可重入锁最常用ReadWriteLock 读写锁读共享、写互斥Semaphore 信号量限流CountDownLatch 闭锁三、Redlock 红锁了解向多个独立 Redis 主节点同时申请锁超过半数节点加锁成功才算拿到锁。优点解决主从异步复制导致锁丢失问题。缺点部署复杂性能差大部分业务不用业界很多人不推荐。高频深挖面试题Q1为什么解锁不能直接 del直接 del 会把其他线程持有的锁删掉。要校验 value线程标识确认是自己的锁再删除并且必须 Lua 保证原子。Q2看门狗什么时候生效调用lock()无参方法时启用如果手动指定 leaseTime 锁过期时间看门狗失效不会自动续期。Q3分布式锁和本地 synchronized 区别synchronized 是 JVM 级锁只在单个 JVM 内生效Redis 分布式锁跨 JVM、跨服务实例。Q4Redisson 可重入底层怎么实现Hash 结构key 锁名称field 线程 IDvalue 重入次数每次加锁 field 计数 1解锁 - 1计数归 0 删除 key。Q5分布式锁有哪些方案Redis 锁、Zookeeper 临时节点锁、数据库乐观锁。ZK强一致性性能弱Redis性能高存在锁失效风险数据库性能最差。一句话背诵总结原生分布式锁用 SET NX EX 原子加锁原生存在锁超时、误删、主从切换锁失效问题Redisson 基于 Lua支持可重入、看门狗自动续期红锁多节点加锁性能差生产很少使用。7.主从复制、哨兵、集群一、主从复制Master-Slave作用读写分离主节点负责写从节点负责读数据自动同步做数据备份。(1)同步流程全量同步从节点首次连接主节点主执行 bgsave 生成 RDB发送给从节点同时记录同步期间的写命令到复制积压缓冲区 repl_backlog。从加载 RDB 到内存然后执行缓冲区里的命令。增量同步正常运行阶段主节点每收到写命令异步复制给从节点主从断连后如果偏移量还在 repl_backlog 内直接增量同步不用全量。(2)核心要点默认异步复制主写完直接返回客户端不等待从同步完成存在数据丢失风险。一主多从从节点只读从节点可以有子从。缺陷没有自动故障转移主节点宕机需要人工切换。二、哨兵 Sentinel哨兵是独立进程集群监控主从节点实现自动故障转移。(1)核心功能监控持续检测主、从节点是否存活。消息通知节点异常推送告警。自动故障转移master 宕机哨兵集群投票挑选健康从节点提升为新 master修改其他从节点让它们复制新主。(2)主观下线、客观下线主观下线单个哨兵检测到主节点无响应单方面标记下线。客观下线quorum法定数量哨兵都判定主节点下线才认定客观下线开启故障转移。(3)选举新 master 规则优先选健康节点优先级高slave-priority复制偏移量最大数据最新runid 最小。(4)缺陷只有一套主从无法水平扩展写能力写压力全部集中在 master适合中小规模。三、Redis Cluster 分片集群⭐重点解决哨兵不能扩容写的问题分片存储数据多主节点分担读写。哈希槽 slot一共 16384 个 slot所有 key 通过CRC16(key)%16384计算归属槽位。把 16384 个 slot 分配给多个 master 主节点每个 master 负责一部分槽从节点作为 master 备份。客户端访问 key计算 slot请求转发到对应 master。故障转移主节点宕机集群内类似哨兵机制把它的从提升为主接管 slot。Cluster 限制高频考点不支持跨 slot 多 key 操作mget、事务如果多个 key 落在不同 slot报错。可以用 hash tag 强制 key 分到同一个槽。只支持 0~16383 共 16384 个槽。Q为什么是 16384 个槽2^1416384。槽太少扩容粒度大槽太多集群节点之间交换槽信息的心跳包占用带宽高16384 是权衡后的选择。高频深挖面试题Q1主从复制 repl_backlog 作用主节点维护环形缓冲区保存最近的写命令从断线重连时对比复制偏移量如果偏移量还在缓冲区直接增量同步避免全量 RDB。Q2哨兵为什么集群部署防止哨兵单点故障多个哨兵投票避免单哨兵误判。一般部署奇数个哨兵3 个。Q3Cluster 扩容原理新增 master 节点手动迁移部分 slot 到新节点迁移过程不阻塞业务。Q4主从异步复制会丢数据吗会。主写入成功还没同步到从master 宕机从升级为主丢失这段数据。Q5Cluster 和哨兵怎么选数据量不大、写压力低只用哨兵数据量大需要分片扩容写选 Cluster。一句话背诵总结主从复制实现读写分离全量 增量同步无自动故障转移哨兵集群监控主从master 宕机自动故障转移但无法扩展写Cluster 采用 16384 哈希槽分片多主分担读写支持扩容跨 slot 多 key 命令受限。8.高频深挖追问Q1Redis 为什么是 16384 个槽2^1416384。太小扩容不好太大占用更多心跳消息带宽。Q2Redis 事务Redis 事务不支持回滚和 MySQL 事务不一样。命令MULTI开启事务EXEC执行DISCARD放弃事务WATCH监控 key。(1)MULTI开启事务后续命令进入命令队列不立即执行。(2)EXEC一次性执行队列里所有命令。(3)WATCH乐观锁监控 key如果 EXEC 前 key 被其他客户端修改事务直接放弃执行。(4)两种异常区分必考语法错误命令写错参数不对整个事务全部不执行。运行时异常命令语法没问题执行报错比如对 String 执行 hget错误命令失败其他正常命令依旧执行不会回滚。核心原因Redis 是简单 KV 数据库设计上不支持事务回滚。Q3管道 Pipeline 和事务区别(1)原理客户端一次性打包多条命令发给 RedisRedis 执行后批量返回结果。减少多次网络往返 RTT提升性能。(2)特点没有事务原子性命令可以部分成功只是网络优化手段命令依旧逐条执行中间其他客户端可以写入。(3)和事务对比事务 MULTI保证原子性但是每条命令依旧单独网络交互无法减少网络次数Pipeline减少网络 RTT不保证原子。区别Pipeline批量打包多条命令减少网络 RTT无事务保证事务 MULTI保证原子执行不能减少网络次数。Q4Lua 脚本作用(1)作用多条命令打包原子执行减少网络开销, Redisson 底层大量使用 Lua, 脚本执行期间其他客户端命令排队等待。(2)特点原子性脚本要么全部执行完要么完全不执行减少网络开销Redis 会缓存脚本可复用Redisson 分布式锁底层大量依靠 Lua 脚本。(3)限制脚本执行不能过长会阻塞 Redis 主线程。生产禁止长时间 Lua。Q5Redis 的 Hash 冲突怎么处理拉链法。数组 链表链表过长会转为 rehash。渐进式 rehash分多次迁移不阻塞主线程。Q6WATCH 底层原理WATCH 是乐观锁标记监控的 key执行 EXEC 前检查 key 版本如果被修改事务取消。单线程下实现没有锁。Q7什么时候用 Pipeline什么时候用 Lua单纯批量读写不需要原子Pipeline需要多条命令原子执行分布式锁判断 删除Lua 脚本。Q8Redis 事务可以保证原子性吗语法错误全部不执行运行异常不回滚。只能保证队列命令一次性排队执行不具备数据库的事务回滚原子。Q9Pipeline 一次可以放多少命令没有硬性限制命令过多缓冲区过大会增加网络压力建议拆分。Q10Lua 脚本和 Redis 事务哪个原子性更强Lua 脚本更强。脚本执行过程其他请求无法插入Redis 事务只是入队执行间隙别的客户端可以修改 key除非搭配 WATCH。一句话背诵总结Redis 事务 MULTIEXEC语法错全部不执行运行异常不回滚Pipeline 打包命令降低网络 RTT无原子Lua 脚本原子执行Redisson 底层大量使用长脚本会阻塞主线程。一句话背诵总结Redis 内存 KV单线程 IO 多路复用持久化 RDB 快照 AOF 日志缓存穿透 / 击穿 / 雪崩三套方案过期 key 惰性 定期删除内存淘汰 8 策略分布式锁推荐 Redisson 看门狗续期主从复制哨兵故障转移Cluster 用 16384 哈希槽分片事务不支持回滚。