一、Redis基础知识
1. Redis是什么?
-
基于内存的键值数据库(NoSQL),支持持久化。
-
单线程模型(6.0+支持多线程I/O),高性能(10万+ QPS)。
-
支持多种数据结构:字符串、列表、哈希、集合、有序集合、Stream等。
2. Redis核心数据类型与使用场景
-
String(字符串):缓存、计数器、分布式锁。
-
Hash(哈希):存储对象(如用户信息)。
-
List(列表):消息队列、最新文章列表。
-
Set(集合):去重、共同好友(交集)。
-
Sorted Set(有序集合):排行榜、带权重的队列。
-
Bitmaps/HyperLogLog/Geo:特定场景优化(如UV统计)。
-
Stream(5.0+):消息队列(类似Kafka)。
3. Redis持久化
-
RDB(快照):
-
定时生成内存快照,文件紧凑,恢复快。
-
缺点:可能丢失最后一次快照后的数据。
-
-
AOF(追加日志):
-
记录写操作命令,支持每秒同步/每次同步。
-
缺点:文件大,恢复慢。
-
-
混合持久化(4.0+):结合RDB和AOF,重启时先加载RDB再重放AOF。
4. Redis高可用
-
主从复制:
-
主节点(Master)写,从节点(Slave)读,异步复制。
-
数据不一致窗口期问题。
-
-
哨兵(Sentinel):
-
监控主从节点,自动故障转移(Master选举)。
-
解决高可用问题,但扩容困难。
-
-
Cluster模式:
-
分片(16384个槽),自动数据分片和故障转移。
-
客户端直连节点,支持动态扩缩容。
-
二、Redis进阶知识
1. 缓存问题与解决方案
-
缓存穿透(查不存在的数据):
-
解决方案:布隆过滤器(Bloom Filter)、缓存空值。
-
-
缓存击穿(热点Key过期):
-
解决方案:互斥锁(分布式锁)、永不过期(逻辑过期)。
-
-
缓存雪崩(大量Key同时过期):
-
解决方案:随机过期时间、集群部署、降级熔断。
-
2. 内存管理与淘汰策略
-
内存淘汰策略(8种):
-
noeviction
(默认策略)
-
行为:内存不足时,新写入操作直接报错(
OOM command not allowed when used memory > 'maxmemory'
)。 -
适用场景:数据绝对不能丢失的场景(如金融核心数据),需确保内存足够或由其他机制处理溢出。
-
volatile-lru
-
行为:从设置了过期时间(TTL)的 Key 中,淘汰最近最少使用(LRU)的 Key。
-
适用场景:缓存场景,允许部分数据丢失,但希望保留热点数据。
-
volatile-lfu
(4.0+)
-
行为:从设置了过期时间的 Key 中,淘汰最不经常使用(LFU)的 Key。
-
适用场景:需要更精确的淘汰逻辑(LFU 比 LRU 更关注访问频率)。
-
volatile-ttl
-
行为:从设置了过期时间的 Key 中,淘汰剩余存活时间最短(TTL 最小)的 Key。
-
适用场景:优先淘汰即将过期的 Key,适合短期缓存数据。
-
volatile-random
-
行为:从设置了过期时间的 Key 中,随机淘汰一个 Key。
-
适用场景:对淘汰逻辑无特殊要求,简单快速。
-
allkeys-lru
-
行为:从所有 Key 中,淘汰最近最少使用(LRU)的 Key(无论是否设置 TTL)。
-
适用场景:纯缓存系统,所有数据都可被淘汰。
-
allkeys-lfu
(4.0+)
-
行为:从所有 Key 中,淘汰最不经常使用(LFU)的 Key。
-
适用场景:需要基于访问频率淘汰数据的缓存系统。
-
allkeys-random
-
行为:从所有 Key 中,随机淘汰一个 Key。
-
适用场景:数据无冷热区分,淘汰任意 Key 对业务影响小。
-
-
如何选择淘汰策略?
-
明确需求
-
是否允许数据丢失?
-
不允许 →
noeviction
(需确保内存足够或使用持久化+扩容)。 -
允许 → 其他策略。
-
-
数据是否有冷热区分?
-
有 →
LRU
或LFU
。 -
无 →
random
或TTL
。
-
-
典型场景推荐
-
缓存系统(所有数据可淘汰):
-
优先选择
allkeys-lru
或allkeys-lfu
(保留热点数据)。
-
-
混合型数据(部分数据永久有效):
-
使用
volatile-lru
或volatile-lfu
,并为可淘汰的 Key 设置 TTL。
-
-
短期缓存(数据自然过期):
-
使用
volatile-ttl
,自动淘汰即将过期的 Key。
-
-
简单场景:
-
allkeys-random
或volatile-random
(性能高,但可能误删重要数据)。
-
-
LRU vs LFU
-
LRU(最近最少使用):
-
适合数据访问模式随时间变化(如新闻热点)。
-
-
LFU(最不经常使用):
-
适合长期稳定的访问模式(如用户画像数据)。
-
-
-
内存优化:
-
使用合适的数据类型(如用Hash代替多个String)。
-
控制Key生命周期,避免BigKey(单Key数据过大)。
-
-
配置方式
maxmemory 8gb maxmemory-policy allkeys-lfu
3. 事务与Lua脚本
-
事务:
-
MULTI
/EXEC
命令,不支持回滚(非原子性)。
-
-
Lua脚本:
-
原子执行复杂逻辑,替代事务。
-
示例:限流、秒杀扣库存。
-
4. 分布式锁
-
实现方式:
-
SET key value NX EX
(原子操作设置过期时间)。 -
避免锁误删:检查唯一标识(如UUID)。
-
-
RedLock算法:
-
多节点部署,半数以上节点加锁成功才算成功。
-
三、Redis性能优化
1. 性能瓶颈分析
-
网络延迟、BigKey、复杂命令(如
KEYS *
)、持久化阻塞。 -
监控工具:
redis-cli --stat
、INFO
命令、slowlog
。
2. Pipeline与批量操作
-
Pipeline批量发送命令,减少RTT(Round Trip Time)。
-
示例:Jedis的
pipelined()
方法。
3. 集群优化
-
数据分片均匀,避免热点Key集中在某节点。
-
合理设置
hash tag
(如{user}:1
)强制Key分配到同一槽。
四、Redis常见面试题
-
Redis为什么快?
-
内存操作、单线程避免上下文切换、I/O多路复用。
-
-
如何保证缓存与数据库一致性?
-
旁路缓存模式(Cache Aside)、延迟双删、订阅Binlog。
-
-
Redis集群如何动态扩缩容?
-
添加节点后使用
redis-cli --cluster reshard
重新分配槽。
-
-
Redis的过期策略?
-
定期删除(随机抽查)+惰性删除(访问时检查)。
-
五、学习建议
-
动手实践:部署Redis集群、模拟高并发场景。
-
源码阅读:单线程模型、RDB/AOF实现。
-
场景设计:结合业务设计缓存方案(如电商秒杀)。