前言
Redis(Remote Dictionary Server),基于 C 语言开发的内存键值数据库。数据主要放在内存,所以读写性能极高,单机 QPS 可达十万级别。 很多人以为 Redis 只能做缓存,其实它能力很强:分布式锁、计数器、限流、消息队列、排行榜都可以实现。
核心特点:
- 内存存储,高性能;
- 单线程模型(Redis6.0 之后多线程处理 IO,命令执行依旧单线程串行);
- 丰富的数据结构;
- 支持持久化,可以把内存数据落盘;
- 支持主从复制、哨兵、集群,实现高可用。
注意:Redis 的单线程指命令执行模块单线程,网络 IO、持久化、删除大 key 等操作是多线程。
一、五种常用数据结构 + 业务场景
1. String 字符串(最基础)
底层:简单动态字符串 SDS 命令示例:
set name "zhangsan" get name incr count # 原子自增适用场景
- 普通缓存:用户信息、商品基础信息;
- 计数器:文章阅读量、点赞数,
incr原子操作; - 分布式 Session 共享;
- 简单限流:记录用户访问次数。
坑:value 不宜过大,建议控制 10KB 以内,大 key 会影响性能。
2. List 列表
底层:双向链表(quicklist),有序,允许重复元素,可以头插、尾插。 命令:
lpush list1 a b rpop list1 lrange list1 0 -1适用场景
- 简单消息队列(lpush + rpop);
- 最新消息列表:首页最新动态;
- 时间轴,朋友圈消息。
缺点:消息丢失、重复消费问题,生产业务消息队列优先 MQ,List 只适合简单临时场景。
3. Hash 哈希
key 对应一个 map 结构,存储多个 field-value。类似 Java 里 HashMap。
hset user:1001 name lisi age 20 hget user:1001 name hgetall user:1001适用场景
- 对象存储:用户信息、商品信息,只需要修改某个字段,不用整体更新;
- 购物车:用户 id 作为 key,商品 id 为 field,数量为 value。
对比 String:如果用 String 存对象,修改单个字段需要序列化 / 反序列化整个对象;Hash 可以单独更新 field。
4. Set 集合
无序,元素不允许重复。支持交集、并集、差集。
sadd set1 a b c smembers set1 sinter set1 set2 # 交集适用场景
- 去重:点赞用户,保证一人只能点赞一次;
- 共同好友(交集);
- 抽奖活动,随机抽取元素。
5. Sorted Set(ZSet 有序集合)
元素不可重复;每个元素带一个 score 分数,根据 score 自动排序。
zadd rank 90 tom 80 jack zrange rank 0 -1 withscores zrevrange rank 0 -1 withscores # 倒序适用场景
- 排行榜:直播间热度、商品销量、积分排行榜;
- 延时任务(score 存时间戳);
- 带权重的队列。
二、Redis 持久化:RDB & AOF
Redis 是内存数据库,重启后内存数据丢失。持久化就是把内存数据保存到磁盘,重启恢复数据。两种方案:RDB、AOF,可以单独开启,也可以同时开启。
2.1 RDB(Redis DataBase)
RDB 是快照持久化:在某个时间点,把内存中全部数据生成一份二进制.rdb文件保存到磁盘。
触发方式
- 手动触发:
save(主线程阻塞)、bgsave(fork 子进程,后台执行,推荐) - 自动触发:配置文件
save 900 1,900 秒至少 1 个 key 改动,则执行 bgsave。
bgsave 原理:调用 fork 创建子进程,子进程拷贝父进程内存页(写时复制 COW),子进程把数据写入 rdb 文件,主线程继续处理请求。
RDB 优点
- 文件体积小,二进制压缩,适合做备份;
- 恢复速度快,故障重启加载 rdb 很快;
- fork 子进程,主线程不阻塞(bgsave)。
RDB 缺点
- 丢失最后一次快照之后的数据:两次快照之间宕机,这段时间数据丢失;
- fork 子进程,当数据量巨大时,fork 会短暂阻塞主线程;
- 无法做到实时持久化。
2.2 AOF(Append Only File)
AOF:日志追加持久化。记录每一条写命令,以文本形式追加到 aof 日志文件。Redis 重启时,重新执行 AOF 里所有命令,恢复数据。
AOF 默认关闭,需要手动开启
appendonly yes
AOF 刷盘策略(appendfsync)
always:每一条写命令都刷盘。安全性最高,几乎不丢数据;性能最差。everysec(默认):每秒刷一次磁盘。最多丢失 1 秒数据,推荐配置,平衡性能和安全。no:交给操作系统自行刷盘,性能最好,丢失数据最多。
AOF 重写机制:AOF 文件持续追加,文件越来越大。Redis 自动触发 AOF Rewrite,把多条命令合并成一条,压缩 AOF 文件,不会丢失数据。重写也是 fork 子进程完成。
AOF 优点
- 数据安全性更高,everysec 最多丢 1 秒数据;
- 日志文本格式,可读性强。
AOF 缺点
- 文件体积比 RDB 大很多;
- 数据恢复速度比 RDB 慢;
- AOF 重写也会 fork 子进程,大数据量有阻塞风险。
2.3 RDB + AOF 同时开启(生产推荐)
- Redis 重启优先加载 AOF 文件(AOF 数据更完整);
- RDB 做冷备份,AOF 保障实时数据;
组合方案兼顾备份能力与数据安全。
三、三大缓存经典问题
3.1 缓存穿透
请求查询不存在的数据,缓存没有命中,请求全部打到数据库。大量请求压垮 DB。
解决方案:
- 缓存空值;
- 布隆过滤器,拦截不存在 key。
3.2 缓存击穿
热点 key 过期,大量并发请求瞬间打到数据库。
解决方案:
- 互斥锁;
- 热点 key 永不过期。
3.3 缓存雪崩
大量 key 在同一时间集体过期,或者 Redis 宕机;大量请求全部访问数据库,数据库压力瞬间崩溃。
解决方案:
- 过期时间增加随机值,打散过期时间;
- Redis 高可用(主从 + 哨兵 / 集群);
- 限流熔断;
- 多级缓存。
四、生产环境最佳实践
- 合理设计 key,规范命名,不要过长;
- 规避大 key,大 key 读写阻塞 Redis;
- 持久化:线上一般开启 AOF everysec + RDB 定时备份;
- 禁止使用 keys 命令,大数据量下阻塞主线程;用 scan 代替;
- 设置内存淘汰策略
maxmemory-policy; - 主从、哨兵、集群保证高可用;
- 缓存数据设置过期时间,不要无限存放。
五、面试高频问答
Q1:Redis 单线程模型怎么理解?
A:Redis 命令执行是单线程串行执行;IO、持久化等操作多线程。单线程避免锁竞争,配合内存操作,性能很高。
Q2:RDB 和 AOF 区别?
A:RDB 是时间点快照,文件小,恢复快,会丢失快照间隔数据;AOF 记录写命令日志,安全性更高,文件大,恢复慢。线上推荐两者同时开启。
Q3:五种数据结构分别适用场景?
A:String 做计数器、基础缓存;List 简单消息队列;Hash 存储对象;Set 去重、交集;ZSet 排行榜。
Q4:AOF 重写是什么?为什么需要?
A:AOF 持续追加,文件越来越大;AOF 重写合并命令,压缩日志体积,不影响原有 AOF 日志。
Q5:缓存雪崩、击穿、穿透三者区别?
A:穿透:查不存在数据;击穿:单个热点 key 过期;雪崩:大量 key 同时过期。
结语
Redis 不只是简单缓存组件,丰富的数据结构让它可以实现很多业务能力。持久化 RDB 与 AOF 是核心考点,要理解两者的取舍:RDB 适合备份,AOF 保障数据安全。同时一定要掌握缓存三大问题,这是 Redis 高频提问。
使用 Redis 最重要的是:内存数据库,做好持久化、内存控制、规避大 key。