Redis
基础
什么是Redis数据库
Redis是高性能的键值型(Key-Value)NoSQL 数据库,所有数据存储在内存中,读写速度非常快。
- 单线程:基于 IO 多路复用,快在于纯内存+单线程避免上下文切换。
支持的数据结构
String(字符串):最基本的类型,支持整数、浮点数操作。
List(列表):链表结构,可做消息队列。
Hash(哈希):适合存储对象。
Set(集合):无序集合,支持交集、并集、差集。
Sorted Set(有序集合):带分数的有序集合,可用于排行榜。
Bitmap / HyperLogLog / Geo:位图、基数统计、地理位置
命令
全局性命令
| 命令 | 含义 |
|---|---|
| keys pattern | 查找符合parttern的key |
| exists key | key是否存在 |
| del keys | 删除key |
| type key | 该key的值的类型 |
| expire key seconds | 为key设置过期时间(秒) |
| ttl key | key的剩余时间,-1为永久,-2为不存在 |
| persist key | 移除过期时间 |
| flushdb | 清空当前数据库 |
| flushall | 清空所有数据库 |
| select index | 选择数据库 |
| auth password | 密码认证 |
字符串命令
| 命令 | 含义 |
|---|---|
| set key value | 指定key的值 |
| get key | 获得key的值 |
| mset keys values | 设置一个或者多个key值 |
| mget keys | 获得一个或者多个key值 |
| setex key seconds value | 设置key的值同时设置过期时间 |
| incr key | 将key值为数字的值+1 |
| decr key | 将key值为数字的值-1 |
| incrby key num | 将key值为数字的值加上num |
| decrby key num | 将key值为数字的值加上num |
哈希命令
| 命令 | 含义 |
|---|---|
| hset key field value | 设置哈希表中field字段的值 |
| hget key field | 获取哈希表中字段的值 |
| hgetall key | 获取哈希表中所有的字段和值 |
| hdel key fields | 删除一个或者多个哈希表字段 |
| hkeys key | 获取哈希表中所有字段名 |
| hvals key | 获取哈希表中的所有值 |
| hincrby key field seconds | 为哈希表中的整数字段加上增量 |
列表命令
| 命令 | 含义 |
|---|---|
| lpush key values | 列表左边插入一个或者多个值 |
| rpush key values | 列表右边插入一个或者多个值 |
| lpop key | 列表左边弹出一个值 |
| rpop key | 列表右边弹出一个值 |
| lrange key start stop | 返回列表范围内的值,0.-1为全部 |
| llen key | 获取列表长度 |
集合命令
| 命令 | 含义 |
|---|---|
| sadd key values | 为集合添加一个或者多个成员 |
| smembers key | 返回集合内的所有成员 |
| sismember key member | 判断member是不是key的成员 |
| srem key members | 删除集合内的一个或者多个成员 |
| sinter keys | 返回多个集合的交集 |
| sunion keys | 返回多个集合的并集 |
有序集合命令
score相同按照成员名称的字典排序
| 命令 | 含义 |
|---|---|
| zadd key score value | 向集合加入或更新一个或者多个成员 |
| zrange key start stop | 返回指定升序分数区间的成员 |
| zrevrange key start stop | 返回指定降序分数区间的成员 |
| zincrby key num member | 为集合内的成员分数加上num |
| zrank key member | 返回成员在集合中的正序排名(0开始) |
| zrevrank key member | 返回成员在集合中的逆序排名 |
持久化机制
RDB(快照):在指定时间间隔内把内存数据写入磁盘。
AOF(追加日志文件):记录每次写操作,重启时可重放日志恢复数据。
混合持久化:RDB + AOF 结合,提高数据安全性与性能。
(也可以配置成纯内存缓存模式,不持久化。)
发布/订阅机制
客户端可以订阅频道,Redis 可以作为消息中间件使用。
适合轻量级的消息通知场景。
事务支持
通过 MULTI / EXEC / WATCH 等命令支持事务,保证一组操作的原子性。
不支持复杂的回滚机制,只能保证命令顺序性执行。
高可用与集群
主从复制(Replication):支持读写分离,主从数据自动同步。
哨兵(Sentinel):实现高可用,自动故障转移。
Cluster 集群模式:数据分片存储,支持水平扩展到上千个节点。
原子性操作
单个命令是原子的,多个客户端同时修改同一个 key,也不会产生数据冲突。
缓存策略
淘汰策略(maxmemory-policy):
noeviction(默认)
allkeys-lru / volatile-lru
allkeys-random / volatile-random
volatile-ttl(优先过期)
穿透:查不到 → null 缓存、布隆过滤器。
击穿: key 过期瞬间打爆 → 互斥锁/逻辑过期。
雪崩:大量 key 同时失效 → 过期时间加随机值、分级预热。
Q&A
为什么快?
基于内存存储,访问延迟低。
单线程模型,无上下文切换。单线程避免了加锁和线程切换的开销。
高效数据结构(哈希表、跳表)。
IO 多路复用,非阻塞网络模型。
持久化如何选?
数据重要 → AOF
恢复速度快 → RDB
两者结合 → 混合
主从复制断网了会怎样?
有积压缓冲区可增量复制,否则全量。
如何避免缓存击穿?
热点 key 加互斥锁。
逻辑过期 + 后台线程异步更新
Redis 如何避免缓存穿透?
缓存空值。
布隆过滤器提前拦截。
Redis 如何避免缓存雪崩?
给过期时间加随机值。
热点数据预热。
多级缓存
Redis 有哪些数据结构?应用场景?
String:缓存对象、计数器、分布式锁。
Hash:存储对象属性。
List:消息队列、时间线。
Set:去重、标签、交并差集。
ZSet:排行榜、延时队列。
Redis 如何实现持久化?
RDB:快照,适合全量备份,恢复快。
AOF:追加日志,数据更完整,体积大。
混合持久化:RDB+部分 AOF,兼顾速度和完整
Redis 的淘汰策略有哪些?
noeviction:不淘汰,写失败。
allkeys-lru / volatile-lru:最近最少使用。
allkeys-random / volatile-random:随机删除。
volatile-ttl:优先删过期时间最早的。
Redis 事务能保证原子性吗?
multi/exec 保证一组命令串行执行。
但不保证隔离性(中间可能被修改)。
可用 watch 实现乐观锁
Redis 如何实现分布式锁?
set key value nx ex 秒数(防死锁)。
Redlock 算法:多节点写成功才算加锁。
Redis 如何实现延时队列?
ZSet:score 存过期时间,定时取出。
List:结合 blpop 阻塞等待。
Redis 如何保证高可用?
主从复制(读写分离)。
Sentinel:监控+故障转移。
Cluster:分布式存储+自动故障转移。
Redis 主从复制的原理?
初次:RDB 全量复制。
正常:偏移量 + 复制积压缓冲区,增量复制。
Redis 为什么使用 16384 个槽?
哈希槽分片,slot=CRC16(key)%16384。
16k 槽数量适中,减少内存开销又能支持分布式。
Redis 如何处理过期 key?
惰性删除:访问时发现过期才删。
定期删除:后台定时随机抽样清理。
Redis 内存满了会怎样?
根据 maxmemory-policy 淘汰数据。
如果策略是 noeviction,则写入失败,报错。
Redis 分布式锁为什么要用 UUID 标识?
防止释放其他客户端的锁,只能释放自己加的。
Redis 集群如何扩容?
新节点加入后,迁移部分 slot。
key 根据 slot 自动分配到新节点。
Redis 如何做大 key 优化?
拆分存储(Hash 拆分成多个小 Hash)。
避免单个 key 存储百万条数据。
用 SCAN 替代 KEYS。
Redis 如何排查性能问题?
INFO 查看 CPU、内存、命令执行。
慢查询日志 slowlog。
客户端连接数、命令 QPS。
内存淘汰命中率。
其他
Redis 支持哪些常见数据结构?
👉 追问:
String 的底层实现是什么?
List 的底层数据结构是什么?双向链表还是压缩列表?
Hash 在什么情况下用 ziplist?什么时候转为 hashtable?
Sorted Set 如何实现有序性?
Q2: 为什么要用跳表(SkipList)实现 Sorted Set?
👉 追问:
跳表的时间复杂度?
为什么不用红黑树?
跳表在集群模式下有什么优势?
二、内存与缓存
Q3: Redis 内存满了会怎样?
👉 追问:
Redis 有哪些内存淘汰策略(LRU、LFU、随机、TTL…)?
LRU 与 LFU 的区别?Redis 是如何实现近似 LRU 的?
如何避免缓存雪崩、缓存穿透、缓存击穿?
Q4: 大 key 问题怎么解决?
👉 追问:
如何快速删除一个大 key?
Hash 大 key 分拆策略?
bigkey 对集群迁移有什么影响?
三、持久化
Q5: Redis 的持久化机制有哪些?
👉 追问:
RDB 和 AOF 的区别?
RDB 的触发方式?
AOF 的三种刷盘策略?
Redis 4.0 混合持久化是什么?为什么要引入?
四、主从复制
Q6: Redis 主从复制原理?
👉 追问:
全量复制和部分复制的区别?
主从延迟的原因有哪些?
主从复制过程中,repl_backlog 的作用?
如果从库落后太多,会发生什么?
五、高可用与集群
Q7: Redis 哨兵(Sentinel)是怎么实现高可用的?
👉 追问:
哨兵如何判断主库挂了?
哨兵选举主库的流程?
quorum 和 majority 的区别?
Q8: Redis Cluster 的槽(slot)机制?
👉 追问:
为什么是 16384 个槽?
数据如何路由到具体节点?
集群迁移数据时,客户端如何感知?
Cluster 的脑裂问题怎么解决?
六、事务与锁
Q9: Redis 事务是怎么实现的?
👉 追问:
MULTI/EXEC 有回滚吗?
WATCH 是如何实现乐观锁的?
Redis 分布式锁怎么实现?
RedLock 算法的争议点?
七、扩展问题
Q10: Redis 为什么这么快?
👉 追问:
单线程模型为什么快?
Redis 6 引入多线程做了什么?
epoll 在其中的作用?
Q11: 线上 Redis 崩了,怎么排查?
👉 追问:
info 命令怎么看内存、持久化、复制?
CPU 飙升可能是什么原因?
如何避免 fork 卡顿?





