基础

什么是Redis数据库

Redis是高性能的键值型(Key-Value)NoSQL 数据库,所有数据存储在内存中,读写速度非常快。

  • 单线程:基于 IO 多路复用,快在于纯内存+单线程避免上下文切换。

支持的数据结构

  • String(字符串):最基本的类型,支持整数、浮点数操作。

  • List(列表):链表结构,可做消息队列。

  • Hash(哈希):适合存储对象。

  • Set(集合):无序集合,支持交集、并集、差集。

  • Sorted Set(有序集合):带分数的有序集合,可用于排行榜。

  • Bitmap / HyperLogLog / Geo:位图、基数统计、地理位置

命令

全局性命令

命令含义
keys pattern查找符合parttern的key
exists keykey是否存在
del keys删除key
type key该key的值的类型
expire key seconds为key设置过期时间(秒)
ttl keykey的剩余时间,-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

为什么快?

  1. 基于内存存储,访问延迟低。

  2. 单线程模型,无上下文切换。单线程避免了加锁和线程切换的开销。

  3. 高效数据结构(哈希表、跳表)。

  4. 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 卡顿?