面试篇: Redis(持续更新)
Redis基础
Redis为什么速度快?
-
纯内存操作:数据存储在内存中,读写速度远高于磁盘数据库。
-
单线程模型:避免多线程竞争和上下文切换,通过I/O多路复用(如epoll)处理高并发请求。
-
高效数据结构:如跳跃表(ZSet)、压缩列表(Hash/List)优化查询效率。
-
协议简单:RESP协议轻量,解析效率高。
注意:Redis 6.0支持多线程I/O处理网络请求,但核心命令执行仍为单线程。
Redis单线程模型的优缺点? 优点: • 无锁设计,避免线程安全问题。
• 原子操作天然支持事务性。
• 适合高吞吐场景(如缓存、计数器)。
缺点**: • 无法利用多核CPU(需通过集群分片解决)。
• 长命令(如KEYS *
)会阻塞后续请求。
数据结构
Redis支持哪些数据类型?应用场景
-
String:缓存、分布式锁(
SETNX
)、计数器(INCR
)。 -
Hash:存储对象(如用户信息),支持字段级操作。
-
List:消息队列(
LPUSH
/BRPOP
)、最新消息列表。 -
Set:标签系统、共同好友(
SINTER
)。 -
ZSet:排行榜(
ZADD
/ZRANGE
)、延迟队列。 -
BitMap:用户签到统计、活跃状态记录。
-
HyperLogLog:基数统计(如UV统计)。
-
Stream:消息队列(支持消费者组)。
ZSet底层实现原理 ZSet通过两种结构实现:
-
跳跃表(SkipList):支持有序性,范围查询时间复杂度为O(log n)。
-
哈希表(Dict):存储元素到分值的映射,分值查询时间复杂度为O(1)。 • 优化:元素较少时使用压缩列表(ziplist),超过阈值后转为跳跃表。
持久化与高可用
RDB和AOF的区别及优缺点
特性 | RDB(快照) | AOF(日志) |
---|---|---|
数据安全性 | 可能丢失最后一次快照后的数据 | 最多丢失1秒数据(appendfsync everysec ) |
恢复速度 | 快(二进制文件直接加载) | 慢(需重放命令) |
文件体积 | 小 | 大 |
适用场景 | 备份、容灾 | 高数据安全要求场景 |
混合持久化(Redis 4.0+):结合RDB快照和AOF增量日志,重启时先加载RDB再重放AOF。
Redis主从复制流程
-
全量同步:从节点首次连接主节点时,主节点生成RDB文件发送给从节点。
-
增量同步:主节点维护环形缓冲区(
repl_backlog
),从节点断线后通过PSYNC
同步增量数据。 -
心跳机制:主从节点通过
PING
/PONG
维持连接状态。
集群与高可用
Redis Sentinel(哨兵)的作用
-
监控:检测主从节点状态。
-
自动故障转移:主节点宕机时,选举新主节点并切换。
-
配置通知:向客户端推送新主节点地址。
缺点:需客户端支持Sentinel协议,分片需手动实现。
Redis Cluster分片原理
-
哈希槽(16384个):通过
CRC16(key) % 16384
计算槽位,每个节点管理部分槽。 -
数据迁移:支持动态扩缩容,槽位可在线迁移。
-
高可用:每个主节点有1~N个从节点,主节点故障时从节点自动接替。
事务与内存管理
Redis事务的ACID特性
-
原子性:事务中命令按顺序执行,但失败后无回滚(部分支持)。
-
隔离性:单线程模型保证事务执行期间无并发干扰。
-
持久性:依赖RDB/AOF配置。
Redis内存淘汰策略 • noeviction
:默认策略,拒绝写入新数据。
• allkeys-lru
:淘汰最近最少使用的键。
• volatile-ttl
:淘汰剩余存活时间最短的键。
• allkeys-random
:随机淘汰任意键。
常见问题解决方案
缓存穿透、击穿、雪崩解决方案
-
穿透:非法请求查询不存在的数据。 • 方案:布隆过滤器拦截非法请求;缓存空值(设置短过期时间)。
-
击穿:热点Key失效后请求压垮数据库。 • 方案:互斥锁重建缓存(
SETNX
);逻辑过期(物理永不过期)。 -
雪崩:大量Key同时过期。 • 方案:随机过期时间;多级缓存(本地缓存+Redis)。
分布式锁实现要点
-
加锁:
SET key unique_value NX EX 30
(原子操作)。 -
解锁:Lua脚本校验值后删除(避免误删)。
-
续期:守护线程定期延长锁时间(如Redisson的看门狗机制)。
提示:面试中需结合具体场景(如电商、社交)举例说明技术选型。