Redis-面试

Redis 基础特性

  • 定义:Redis(Remote Dictionary Server)是一款开源的高性能键值对数据库,基于内存存储,支持持久化,采用单线程模型(核心网络 IO 模块)。
  • 核心优势
    • 速度快:内存操作 + 单线程避免上下文切换,QPS 可达 10 万 +;

    • 支持多数据结构:不止字符串,还包含哈希、列表、集合等;

    • 功能丰富:支持持久化、过期淘汰、事务、发布订阅、Lua 脚本等;

    • 高可用:提供主从复制、哨兵、集群方案;

    • 跨平台:兼容 Linux、Windows 等,且支持多种客户端语言。

Redis 核心数据结构

五大基础数据结构及应用场景

数据结构

底层实现(关键版本)

核心命令

典型应用场景

String

简单动态字符串(SDS)

SET、GET、INCR、APPEND

计数器(文章阅读量)、缓存用户信息

Hash

哈希表(拉链法解决冲突)

HSET、HGET、HMGET、HDEL

存储对象(用户资料:id→{name,age})

List

双向链表(3.2 前)/ 压缩列表(3.2 后)

LPUSH、LPOP、LRANGE

消息队列、最新消息排行(如朋友圈)

Set

哈希表 / 整数集合

SADD、SISMEMBER、SUNION

标签(用户兴趣标签)、共同好友计算

ZSet

跳表 + 哈希表

ZADD、ZRANGE、ZSCORE

排行榜(游戏积分排行、商品销量榜)

高级数据结构

  • HyperLogLog:基于概率统计的基数计数结构,占用内存极小(约 12KB),适用于 “统计 UV”(如网站独立访客),误差率约 0.81%。

  • GeoHash:将经纬度编码为字符串,支持附近地点查询(如 “外卖 App 附近商家”),核心命令GEOADD(添加坐标)、GEORADIUS(搜索半径内地点)。

  • BitMap:按位存储数据,1 字节可存 8 个状态,适用于 “签到统计”(如用户月度签到)、“活跃用户标记”,核心命令SETBIT(设定位)、BITCOUNT(统计 1 的个数)。

Redis 持久化机制

        持久化的核心目的是防止内存数据丢失,Redis 提供两种持久化方案,可单独使用或结合使用。

RDB(Redis Database)

  • 原理:在指定时间间隔内,将内存中当前数据集快照写入磁盘(生成.rdb文件),恢复时直接加载该文件到内存。

  • 触发方式
    • 手动触发:SAVE(阻塞 Redis 进程,不推荐)、BGSAVE(fork 子进程执行快照,主进程不阻塞);

    • 自动触发:配置文件中save <秒数> <修改次数>(如save 60 1000表示 60 秒内修改 1000 次则触发 BGSAVE)。

  • 优缺点
    • 优点:文件体积小、恢复速度快,适合全量备份(如每日凌晨备份);

    • 缺点:快照间隔内数据易丢失(如 1 分钟内宕机,该分钟数据丢失),fork 子进程时会占用额外内存(Copy-On-Write 机制)。

AOF(Append Only File)

  • 原理:将 Redis 的每一条写命令(如 SET、HSET)以日志形式追加到.aof文件,恢复时重新执行文件中的命令以重建数据。
  • 触发方式:依赖配置文件中的appendfsync参数:
    • always:每执行一条命令就刷盘,数据零丢失,但性能最差;

    • everysec:每秒刷盘一次,最多丢失 1 秒数据,性能与安全性平衡(默认值);

    • no:由操作系统决定刷盘时机,数据丢失风险高。

  • AOF 重写
    • 问题:AOF 文件会随命令增多而变大,恢复速度变慢;

    • 解决:通过BGREWRITEAOF命令(或自动触发),合并相同 key 的命令(如SET a 1→SET a 2合并为SET a 2),生成更小的 AOF 文件。

  • 优缺点
    • 优点:数据安全性高(可配置每秒刷盘),文件可读性强(文本格式);

    • 缺点:文件体积大、恢复速度慢,写命令追加会消耗额外 IO。

RDB 与 AOF 的选择

  • 追求高性能 + 快速恢复:使用 RDB(如缓存场景,可接受少量数据丢失);
  • 追求数据安全性:使用 AOF(如金融场景,需避免数据丢失);
  • 生产环境推荐:RDB+AOF 结合(AOF 保证数据不丢失,RDB 用于快速恢复)。

Redis 过期键删除与内存淘汰

过期键删除策略

Redis 同时使用三种策略平衡 “数据准确性” 与 “性能消耗”:

  • 惰性删除:只有当访问某个 key 时,才判断是否过期,过期则删除。优点:不占用额外 CPU;缺点:过期 key 未访问时会占用内存(内存泄漏风险)。
  • 定期删除:每隔一段时间(默认 100ms),随机抽取部分过期 key 进行删除。优点:避免内存泄漏;缺点:可能有少量过期 key 未及时删除。
  • 内存淘汰:当内存达到maxmemory阈值时,触发内存淘汰策略,删除部分 key 释放内存(即使 key 未过期)。

内存淘汰策略

配置参数:maxmemory-policy <策略名>,Redis 4.0 后新增两种 LFU 策略:

策略名

含义

volatile-lru

设置了过期时间的 key 中,删除最近最少使用(LRU)的 key

allkeys-lru

所有 key中,删除最近最少使用的 key(推荐,通用缓存场景)

volatile-lfu

从设置了过期时间的 key 中,删除最近最少频率使用(LFU)的 key

allkeys-lfu

从所有 key 中,删除最近最少频率使用的 key(适合访问频率差异大的场景)

volatile-random

从设置了过期时间的 key 中,随机删除 key

allkeys-random

从所有 key 中,随机删除 key

volatile-ttl

从设置了过期时间的 key 中,删除剩余生存时间(TTL)最短的 key

noeviction

不删除任何 key,内存满时拒绝新写命令(默认策略,不推荐生产使用)

Redis 高可用方案

主从复制(基础高可用)

  • 核心作用:实现数据备份(从节点复制主节点数据)、负载均衡(读请求分发到从节点)。
  • 复制流程
    • 从节点执行SLAVEOF <主节点IP> <端口>,发送 SYNC 命令;

    • 主节点执行 BGSAVE 生成 RDB 文件,同时记录后续写命令到复制缓冲区;

    • 主节点发送 RDB 文件给从节点,从节点加载 RDB 恢复数据;

    • 主节点发送复制缓冲区的写命令,从节点执行命令,最终与主节点数据一致。

  • 注意点:默认是 “只读从节点”(slave-read-only yes),避免从节点写入数据导致数据不一致;支持 “链式复制”(从节点可作为其他从节点的主节点),减轻主节点压力。

哨兵(Sentinel)

  • 核心作用:解决主从复制的 “主节点故障自动切换” 问题,实现高可用。
  • 核心功能
    • 监控:实时检查主节点、从节点是否存活;

    • 自动故障转移:主节点宕机后,从哨兵中选举新主节点,并重配置其他从节点指向新主;

    • 通知:通过 API 向客户端或管理员发送故障通知。

  • 部署建议:哨兵节点至少 3 个(奇数,避免脑裂),且与主从节点分开部署(避免单点故障)。

Redis Cluster(分布式集群)

  • 核心作用:解决 “单机内存上限” 问题,实现数据分片存储(横向扩展),同时支持高可用。
  • 核心特性
    • 数据分片:将所有 key 通过 CRC16 算法计算哈希值,映射到 16384 个哈希槽(slot),每个节点负责部分槽;

    • 高可用:每个主节点至少有一个从节点,主节点宕机后,从节点自动升为主节点;

    • 去中心化:无中心节点,客户端可连接任意节点发送请求,节点间通过 Gossip 协议通信。

  • 关键命令:CLUSTER MEET(添加节点到集群)、CLUSTER ADDSLOTS(为节点分配槽)、CLUSTER REPLICATE(设置从节点)。

Redis 常见问题与优化

缓存穿透

  • 问题:请求查询 “不存在的 key”(如恶意查询 id=-1 的用户),Redis 无法命中,请求直接穿透到数据库,导致数据库压力过大。
  • 解决方案
    • 缓存空值:对不存在的 key,缓存一个空值(如SET -1 "" EX 300),并设置较短过期时间;

    • 布隆过滤器:在 Redis 前部署布隆过滤器,不存在的 key 直接被过滤(如用 Redis 的 HyperLogLog 或单独布隆过滤器组件)。

缓存击穿

  • 问题:某个 “热点 key” 过期瞬间,大量请求同时穿透到数据库(如秒杀商品的库存 key 过期)。
  • 解决方案
    • 互斥锁:当 key 过期时,只有一个线程能获取锁去数据库查询,其他线程等待重试(如用 Redis 的SETNX命令实现锁);

    • 热点 key 永不过期:对热点 key 不设置过期时间,通过后台线程定期更新数据(需注意内存占用)。

缓存雪崩

  • 问题:大量 key 在同一时间过期,或 Redis 集群宕机,导致所有请求穿透到数据库,引发数据库雪崩。
  • 解决方案
    • 过期时间随机化:为 key 设置过期时间时,添加随机值(如EX 3600 + rand(0, 600)),避免集中过期;

    • 服务熔断 / 降级:当数据库压力过大时,拒绝部分非核心请求,或返回默认值(如用 Sentinel 或 Hystrix 实现);

    • Redis 集群高可用:部署哨兵或 Redis Cluster,避免单点故障导致整个缓存不可用。

Redis 单线程模型为什么快?

  • 核心原因:Redis 的单线程仅负责 “网络 IO” 和 “命令执行”,避免了多线程的上下文切换和锁竞争;
  • 辅助原因:
    • 内存操作:数据都在内存中,读写速度远快于磁盘;

    • IO 多路复用:使用 epoll(Linux)、kqueue(BSD)等 IO 多路复用模型,可同时处理大量客户端连接,且无阻塞;

    • 高效数据结构:如跳表、压缩列表等,减少数据操作的时间复杂度。

Redis 与 Memcached 的区别

特性维度RedisMemcached
数据类型丰富:String, Hash, List, Set, Sorted Set, Stream, Geo 等单一:只支持 String 类型的 Key-Value
持久化支持:提供 RDB(快照)和 AOF(日志)两种方式,数据可恢复不支持:纯内存缓存,重启数据即丢失
分布式支持 (Redis Cluster, 主从复制, 哨兵模式)支持 (客户端分片,或通过代理如 Twemproxy)
性能极高 (单机10万+ QPS,依赖网络IO)
(但复杂命令如 ZRANGE 会慢一些)
极高 (单机10万+ QPS,依赖网络IO)
(模型简单,性能略高于 Redis 简单命令)
内存管理多种策略:LRU, LFU, TTL, 最大内存限制等类似:LRU, TTL, 最大内存限制
事务支持 (MULTI/EXEC)不支持 (但提供 CAS 命令保证原子性)
应用场景全能型:缓存、会话共享、消息队列、排行榜、分布式锁、地理位置等单一型:简单的键值缓存,用于减轻数据库负载
语言支持极广:官方支持 C/C++,社区有几乎所有语言的客户端 (Java, Python, Go, ...)广泛:多种语言客户端
附加功能发布订阅、Lua 脚本、模块化扩展多线程、高并发
典型部署独立服务器/集群部署独立服务器/集群部署
优点功能强大、数据类型丰富、持久化、高可用、社区活跃超简单、超快(对于简单KV)、多线程性能高、内存利用率稍好
缺点消耗更多内存(存储元数据)、单线程模型(6.0+多线程IO)复杂命令可能阻塞功能单一、无法持久化、需要客户端实现分布式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值