☰
Redis 面试题全总结:2 万字详解,值得收藏
2026/10/11 1:46:38 网站建设 项目流程

Redis(Remote Dictionary Server,远程字典服务)是一个开源的、基于内存的高性能键值数据库,由 Salvatore Sanfilippo 使用 C 语言编写,既可以作为数据库、缓存,也可以作为消息中间件使用。


一、Redis 基础篇

1. 什么是 Redis?它有哪些特点?

Redis 的核心特点可以归纳为以下几点:

  • 基于内存:数据存储在内存中,读写速度极快,单机 QPS 可以达到 10 万以上。

  • 持久化:提供 RDB 和 AOF 两种持久化方式,可以把数据保存到磁盘,防止重启丢失。

  • 数据结构丰富:不只是简单的 key-value,还支持 String、List、Hash、Set、ZSet、BitMap、HyperLogLog、GEO、Stream 等多种数据结构。

  • 单线程模型:Redis 6.0 之前,命令执行是单线程的,避免了多线程的上下文切换和锁竞争问题。

  • 功能丰富:支持发布订阅、事务、Lua 脚本、过期删除、内存淘汰、主从复制、哨兵、集群等。

  • 支持高可用和分布式:通过 Sentinel 实现高可用,通过 Cluster 实现水平扩展。

2. Redis 为什么这么快?

主要原因包括:

  • 纯内存操作:所有数据都保存在内存中,不涉及磁盘 IO,这是速度快的根本原因。

  • 单线程避免切换开销:Redis 6.0 之前核心命令执行是单线程的,避免了上下文切换、锁竞争、CPU 缓存失效等问题。

  • 高效的数据结构:例如 String 使用 SDS,Hash 使用压缩列表或哈希表存储。

  • IO 多路复用:使用 epoll/select/kqueue 等技术,一个线程可以同时监听多个客户端连接。

  • 采用 Reactor 网络模型:网络部分采用事件驱动模型,把连接、读、写、关闭等都转化为事件来处理。

注意:Redis 6.0 引入了多线程,但多线程只用于「网络 IO 的读写」部分,命令的真正执行仍然是单线程的。

3. Redis 和 Memcached 有什么区别?

对比维度RedisMemcached
数据结构String、List、Hash、Set、ZSet 等多种仅支持简单的 key-value
持久化支持 RDB、AOF不支持,重启数据丢失
线程模型单线程执行命令(6.0 后网络多线程)多线程
高可用支持主从、哨兵、集群不支持原生高可用,需要客户端实现
过期策略惰性删除 + 定期删除惰性删除
内存管理可设置内存淘汰策略内存分配采用 Slab,容易产生碎片
value 大小最大 512MB最大 1MB

总结:需要复杂数据结构、持久化、高可用,选择 Redis;只是简单缓存且数据量极大、对数据类型没有要求,可以考虑 Memcached。大多数现代系统中,Redis 基本已成为默认选择。

4. Redis 的单线程模型是怎样的?为什么后来又引入多线程?

Redis 整体上采用基于事件驱动的 Reactor 模型:

  1. 客户端建立连接后,将 socket 注册到 IO 多路复用器(epoll)中。

  2. socket 上有事件发生时,把事件放入队列。

  3. 单线程的事件处理器依次取出事件,进行连接应答、命令读取、命令执行、结果返回。

早期坚持单线程,是因为性能瓶颈主要在内存和网络上,而不是 CPU,且单线程可避免锁竞争,代码更简单。

随着网络硬件发展,单个主线程处理网络 IO 的读写逐渐成为瓶颈,因此Redis 6.0 引入 IO 多线程:多线程只负责 socket 的读写解析,命令执行仍由主线程完成。

5. Redis 的 key 和 value 最大能有多大?

单个 key 最大为 512MB 左右,单个 value 最大也是 512MB。实际生产中不建议存放过大的 key 或 value,因为会导致网络传输缓慢、内存分配压力大、删除时阻塞等问题,也就是所谓的「大 key」问题。


二、数据类型与底层数据结构篇

1. Redis 支持哪些数据类型?各自适用什么场景?

数据类型特点典型场景
String最基础类型,可存字符串、整数、浮点数缓存对象、计数器、分布式锁、Session 共享
Hash适合存储对象,可单独更新某个字段用户信息、购物车、商品详情
List有序、可重复的双向链表消息队列、最新消息列表、分页浏览
Set无序、不可重复标签、共同关注、抽奖去重、随机推荐
ZSet带分数的有序集合排行榜、延时队列、带权重的消息队列

高级数据结构:BitMap(签到、在线状态)、HyperLogLog(UV 统计)、GEO(附近的人)、Stream(消费者组模式的消息队列)。

2. 五种基本数据类型的底层数据结构分别是什么?

数据类型底层实现
StringSDS(简单动态字符串),整数会使用 int 编码
ListQuickList(ZipList + LinkedList),Redis 7.0 中已用 ListPack 替代 ZipList
HashListPack(或 ZipList)+ 哈希表,元素较少时为紧凑结构
Set整数集合(intset)或哈希表,元素较少且全为整数时为 intset
ZSetListPack(或 ZipList)+ 跳表 skiplist 与哈希表组合

3. 什么是 SDS?相比 C 字符串有什么优势?

SDS 即 Simple Dynamic String(简单动态字符串),优势包括:

  • O(1) 获取长度:内部维护了 len 字段,不需要遍历到\0计算长度。

  • 杜绝缓冲区溢出:拼接前检查空间是否足够,不够自动扩容。

  • 减少内存重分配次数:采用空间预分配和惰性空间释放策略。

  • 二进制安全:通过 len 判断字符串结束,可存任意二进制数据。

4. Redis 的 Hash 与 Java 的 HashMap 有什么区别?

  • 扩容方式不同:Java HashMap 一次性完成 rehash,可能短暂停顿;Redis 采用渐进式 rehash,把过程分摊到多次操作中。

  • 存储结构不同:Redis Hash 元素较少时采用紧凑的 ListPack 或 ZipList,元素多了才转为哈希表。

  • 哈希函数不同:Redis 使用 SipHash 等算法,采用链地址法解决冲突。

渐进式 rehash 的核心思想是:维护 ht[0] 和 ht[1],rehash 过程中新数据写入 ht[1],每次增删改查时顺带把 ht[0] 中的一部分桶迁移到 ht[1],直到迁移完成。

5. ZSet 的跳表结构是怎样的?为什么用跳表而不用红黑树?

ZSet 在元素较多时使用「跳表 + 哈希表」结构:跳表用于按分数排序和范围查询,哈希表用于根据成员快速定位分数。

跳表是一种多层链表结构,每一层都是下一层的抽样索引,查找时从最高层开始向下跳跃,平均时间复杂度为 O(logN)。

选择跳表而非红黑树的原因:

  • 跳表实现更简单,容易理解和维护,不容易写出 bug。

  • 跳表支持快速的范围查询,红黑树的区间查找相对复杂。

  • 跳表更符合 Redis 对简单、高效、可预测的追求。

6. 如何使用 Redis 实现排行榜?

排行榜是 ZSet 最经典的应用场景:

shell

# 增加或更新玩家分数 ZADD rank 100 player1 # 给玩家加分 ZINCRBY rank 50 player1 # 查询玩家排名(从 0 开始,降序) ZREVRANK rank player1 # 查询某个玩家的分数 ZSCORE rank player1 # 查询前 10 名 ZREVRANGE rank 0 9 WITHSCORES # 查询分数在 80 到 200 之间的玩家 ZRANGEBYSCORE rank 80 200 WITHSCORES

数据量大时,需使用ZREMRANGEBYRANK定期清理榜尾数据,避免 ZSet 无限增长。

7. 如何使用 Redis 实现一个简单的消息队列?

方式一:使用 List。生产者LPUSH/RPUSH,消费者BRPOP/BLPOP阻塞读取。

shell

# 生产者 LPUSH queue "message1" # 消费者(阻塞等待) BRPOP queue 0

优点是简单、可靠;缺点是没有消息确认机制,消费失败后消息会丢失。

方式二:使用发布订阅 Pub/Sub。SUBSCRIBE订阅,PUBLISH发布。缺点是消息无法持久化,断线期间消息丢失。

方式三:使用 Stream(Redis 5.0+)。支持消费者组、消息确认、消息回溯,是最完善的方案。

shell

# 生产消息 XADD mystream * field value # 创建消费者组 XGROUP CREATE mystream group1 0 # 消费者读取消息 XREADGROUP GROUP group1 consumer1 COUNT 1 STREAMS mystream > # 确认消息 XACK mystream group1 消息ID

实际生产中,要求不高的场景可用 List 实现简单异步解耦;可靠性要求高的场景建议使用 Stream 或专业消息中间件如 Kafka、RocketMQ。


三、持久化机制篇

1. Redis 有哪些持久化方式?分别是怎么实现的?

  • RDB(Redis DataBase):在指定时间间隔内,把内存中的数据集快照写入磁盘。fork 一个子进程负责写入临时文件,写完后替换旧 RDB 文件。触发方式包括手动SAVE/BGSAVE和配置文件save条件自动触发。

  • AOF(Append Only File):以追加日志形式记录每一条写命令。重启时通过重新执行 AOF 文件中的命令来恢复数据。三种刷盘策略:always、everysec(默认)、no。

  • 混合持久化(Redis 4.0+):AOF 重写时,先使用 RDB 格式写入当前数据快照,再把重写期间的增量命令以 AOF 格式追加,兼顾快速加载和减少数据丢失。

2. RDB 和 AOF 各有什么优缺点?如何选择?

对比维度RDBAOF
数据完整性可能丢失最后一次快照到宕机之间的数据默认 everysec 最多丢失 1 秒数据,always 更安全
文件大小紧凑的二进制文件,体积小记录命令,文件通常更大
恢复速度快,直接加载快照慢,需要重放所有命令
对性能影响fork 子进程时有短暂开销,写时复制默认每秒刷盘影响较小,always 影响较大
启动优先级低高,同时存在时优先加载 AOF

官方建议两种都开启。对数据安全性要求高,优先保障 AOF;对恢复速度有要求且能容忍少量数据丢失,可同时开启 RDB。生产环境最常见的是「RDB 做冷备 + AOF everysec」的组合。

3. AOF 重写是什么?为什么要重写?

AOF 文件会随着写命令增加不断变大,文件过大会导致磁盘占用高、恢复慢。AOF 重写就是通过读取当前内存中的数据状态,生成一份新的、体积更小的命令文件来替换旧的 AOF 文件,相当于把多条冗余命令「压缩」成一条。

例如对 key 执行了 100 次INCR,原本 AOF 记录了 100 条 INCR 命令,重写后可能只记录一条SET命令。重写过程由 fork 出的子进程完成,期间新的写命令会同时写入 AOF 缓冲和重写缓冲,重写完成后把重写缓冲的命令追加到新文件中,再原子地替换旧文件。

4. Redis 重启时,RDB 和 AOF 同时存在会优先加载哪个?

会优先加载 AOF 文件。因为 AOF 默认采用 everysec 刷盘,更新频率通常更高,数据比 RDB 更完整。当 AOF 关闭或文件不存在时,Redis 才会加载 RDB 文件。因此生产环境中如果同时开启两种持久化,恢复时需要以 AOF 的结果为准。


四、过期删除与内存淘汰篇

1. Redis 的过期删除策略有哪些?

Redis 中设置了过期时间的 key 不会在过期瞬间被立即删除,而是通过「惰性删除 + 定期删除」两种策略配合完成清理:

  • 惰性删除:客户端访问某个 key 时,先判断是否过期。已过期就删除并返回空,未过期则正常返回值。优点是节省 CPU;缺点是如果过期 key 一直不被访问,就会长期占用内存。

  • 定期删除:Redis 内部默认每 100ms 左右执行一次过期扫描,随机抽取一批设置了过期时间的 key 判断是否过期,并根据过期比例决定是否继续本轮扫描。优点是内存释放更及时;缺点是扫描本身消耗 CPU。

为什么不用定时删除:如果为每个 key 都设置一个精确的过期定时器,当 key 数量很大时会产生大量定时事件,严重消耗 CPU,拖垮 Redis 的吞吐能力。

实际执行中,两种策略互为补充:惰性删除兜底读写路径,定期删除负责主动清理长期不被访问的过期 key,从而在 CPU 和内存之间取得平衡。

2. Redis 提供了哪些内存淘汰策略?分别是什么意思?

策略含义
noeviction不淘汰任何 key,内存不足时写入命令报错
allkeys-lru所有 key 中淘汰最近最少使用的
allkeys-lfu所有 key 中淘汰访问频率最低的
allkeys-random所有 key 中随机淘汰
volatile-lru设置了过期时间的 key 中淘汰最近最少使用的
volatile-lfu设置了过期时间的 key 中淘汰访问频率最低的
volatile-random设置了过期时间的 key 中随机淘汰
volatile-ttl设置了过期时间的 key 中淘汰剩余生存时间最短的

LRU 和 LFU 的区别(高频考点):

  • LRU(Least Recently Used):关注「最近一次被访问的时间」,淘汰最久没有被访问的 key。假设最近访问过的数据更可能再次被访问。

  • LFU(Least Frequently Used):关注「一段时间内的访问频率」,淘汰访问次数最少的 key。更能保留长期高频的热点数据。

需要注意,Redis 实现的 LRU 是「近似 LRU」,通过随机采样评分的方式判断,默认每次采样 5 个 key,在精度和性能之间做折中。LFU 则根据访问次数和衰减时间综合计算热度。

3. 什么是缓存穿透?如何解决?

缓存穿透指查询一个根本不存在的数据,既不在缓存中,也不在数据库中。每次这样的恶意请求都会穿透缓存,给数据库造成巨大压力。

常见解决方案:

  1. 缓存空值:当数据库查询不到某个 key 时,仍然在缓存中写入一个带短过期时间的空对象。后续相同的非法 key 请求会命中这个空缓存,不再访问数据库。缺点是额外占用缓存空间,需要设置合理的过期时间。

  2. 布隆过滤器:在缓存之前加一层布隆过滤器,将所有合法 key 先登记到过滤器中。请求进来时先判断 key 是否可能存在,如果判断为不存在,则直接拒绝请求。布隆过滤器可能出现少量误判为「可能存在」,但不会漏判「一定不存在」。

使用 RedisBloom 模块可快速实现布隆过滤器:

shell

# 创建布隆过滤器,允许 0.01 的错误率,初始容量 100000 BF.RESERVE user:bf 0.01 100000 # 添加元素 BF.ADD user:bf 10086 # 判断元素是否存在 BF.EXISTS user:bf 10086 # 批量添加 BF.MADD user:bf 10010 10011 10012

如果不想引入额外模块,也可以使用 BitMap 自己实现简易布隆过滤器,核心思想是使用多个哈希函数将 key 映射到位图中的多个 bit 位,查询时只要有一个 bit 不为 1,就一定不存在。

4. 什么是缓存击穿?如何解决?

缓存击穿指某个热点 key 在过期瞬间,大量并发请求同时穿过缓存直接打到数据库。它与缓存穿透的区别是:击穿针对的是「一个确实存在的热点 key」,而穿透针对的是「根本不存在的 key」。

常见解决方案:

  1. 互斥锁:缓存失效后,只允许一个请求去数据库加载数据并回写缓存,其他请求等待锁释放后重新读取缓存。可以使用 Redis 的SET key value NX EX实现简单的互斥锁。

  2. 逻辑过期:给缓存 value 附带一个逻辑过期时间字段,而不是让 Redis 真正删除 key。读取时发现逻辑过期,先返回旧值,同时异步重建缓存,避免请求集中打到数据库。

  3. 永不过期:对极度核心的热点数据,不设置 Redis 过期时间,而是通过单独任务手动更新缓存,保证热点 key 始终存在。

5. 什么是缓存雪崩?如何解决?

缓存雪崩指大量缓存 key 在同一时间过期,或者 Redis 实例宕机,导致大量请求同时落到数据库,从而拖垮整个系统。它和缓存击穿的区别在于:击穿是单个热点 key 失效,雪崩是大量 key 同时失效。

解决方案主要包括:

  1. 过期时间加随机值:在原有基础上叠加随机值,把 key 的过期时间打散,避免同一时刻大量 key 同时过期。

  2. 多级缓存:本地缓存、Redis、数据库组成多级体系,即使 Redis 失效,本地缓存仍能抵挡一部分流量。

  3. 限流降级:对数据库访问进行限流和熔断,必要时返回兜底数据或默认文案。

  4. 提高高可用性:通过主从复制、哨兵、集群保证 Redis 本身不会轻易整体宕机。

6. 如何保证缓存与数据库的数据一致性?

核心矛盾在于:缓存和数据库是两套系统,任何跨系统的双写都无法做到严格意义上的强一致,最终只能选择更合适的最终一致性方案。

常见策略:

  1. 先更新数据库,再删除缓存:使用最广泛的方案。更新数据库成功后删除对应缓存 key,后续请求重新从数据库加载并写入缓存。它比「先删缓存再更新数据库」出现脏数据的概率更低。

  2. 延迟双删:更新数据库前先删除缓存,更新数据库后再延迟一段时间删除一次缓存,以清理并发读写产生的旧值。

  3. 通过 Binlog 异步更新缓存:数据库更新后,通过 Canal 等组件监听 Binlog,异步刷新或删除缓存。这样缓存更新与业务逻辑解耦,一致性更可控。

  4. 设置合适的过期时间兜底:即使更新链路出错,缓存也会因为过期而被删除,避免脏数据长期存在。

实际工作中,如果业务能容忍短暂不一致,推荐优先使用「先更新数据库,再删除缓存 + 缓存过期时间兜底」,简单且不易出错。


五、事务、管道与 Lua 篇

1. Redis 事务是怎么实现的?它真的具备原子性吗?

Redis 事务通过MULTI、EXEC、DISCARD、WATCH四个命令实现。核心流程是:执行MULTI开启事务,之后客户端发送的命令会被暂存到队列中,执行EXEC时按顺序一次性执行队列中的所有命令。

shell

# 开启事务 MULTI # 以下命令先进入队列,不会立即执行 SET user:1:name "Tom" INCR user:1:visit EXPIRE user:1:name 3600 # 执行队列中的所有命令 EXEC

Redis 事务并不具备传统数据库那样的强原子性,需要区分两类错误:

  • 语法或参数错误:命令在入队时就被发现语法错误或参数错误,整个事务的所有命令都不会执行。

  • 运行时错误:命令入队时合法,但执行时才发生错误(例如对 String 类型执行 List 命令),只有出错的命令失败,其他命令仍然继续执行。

也就是说,Redis 事务保证的是「命令按顺序排队、执行期间不被其他客户端命令插入」,而不是传统数据库中的回滚原子性。

2. WATCH 命令的作用是什么?

WATCH用来实现乐观锁。在事务开始前,客户端可以WATCH一个或多个 key。执行EXEC时,如果被监视的 key 在事务执行前被其他客户端修改过,整个事务会放弃执行并返回 nil。

shell

# 监视余额 key WATCH account:balance # 读取余额并判断 GET account:balance # 开启事务并扣减余额 MULTI DECRBY account:balance 100 EXEC

如果其他客户端在WATCH之后、EXEC之前修改了account:balance,本次EXEC会失败,客户端可以重试。这种方式常用于「先读后写」且不希望被并发修改覆盖的场景。

3. Pipeline 管道是什么?有什么作用?

Pipeline(管道)是一种批量发送命令、批量接收结果的机制。普通情况下,客户端每发送一条命令都要等待 Redis 返回结果后再发下一条,往返时间 RTT 浪费严重。使用 Pipeline 后,客户端可以把多条命令一次性发送给 Redis,Redis 依次执行后再一次性返回所有结果。

shell

# 一次性发送多条命令,而不是逐条等待 SET a 1 SET b 2 SET c 3 INCR a GET a

Pipeline 的核心价值是减少网络 RTT,而不是减少命令执行时间。它适合大量独立命令的批处理场景。注意 Pipeline 并不保证事务原子性,命令之间仍然可以被其他客户端命令穿插执行。

4. Redis 如何使用 Lua 脚本?它有什么优点?

Redis 从 2.6 版本开始支持 Lua 脚本,通过EVAL或EVALSHA执行。脚本在 Redis 服务端由单线程顺序执行,因此脚本内部的多条命令天然具备原子性,执行期间不会被其他客户端命令打断。

shell

# 语法:EVAL 脚本 numkeys key1 key2 ... arg1 arg2 ... EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey myvalue # 原子地扣减库存并判断结果 EVAL "if redis.call('GET', KEYS[1]) >= ARGV[1] then return redis.call('DECRBY', KEYS[1], ARGV[1]) else return -1 end" 1 stock:1001 1

Lua 脚本的主要优点:

  • 原子性:脚本中所有命令作为一个整体执行,不需要额外加锁。

  • 减少网络开销:多条操作一次发送,减少 RTT。

  • 逻辑复用:脚本可以缓存在 Redis 中,后续用EVALSHA按 SHA1 执行,减少脚本重复传输。

使用 Lua 时要注意避免长耗时脚本,因为脚本执行期间整个 Redis 会阻塞。Redis 也提供了lua-time-limit等保护机制。

5. 事务、Pipeline 和 Lua 有什么区别?

对比维度事务PipelineLua 脚本
核心目的保证命令排队按顺序执行减少网络 RTT保证多条命令原子执行
是否原子不保证回滚原子性不保证原子性保证原子性
执行期间是否阻塞其他命令EXEC 执行队列时不会被其他命令插入命令之间可能被其他客户端命令穿插脚本执行期间阻塞全部其他命令
典型场景乐观锁、简单串联操作批量读写、初始化数据复杂条件判断、原子扣减、分布式锁释放

简单理解:Pipeline 解决「网络耗时」,事务解决「执行顺序」,Lua 解决「多条命令原子性」。


六、主从复制、哨兵与集群篇

1. Redis 主从复制的工作流程是怎样的?

主从复制用于实现数据冗余和读写分离。核心流程分为全量同步和增量同步两个阶段:

  • 全量同步:从节点首次连接主节点时,执行PSYNC ? -1请求全量同步。主节点执行BGSAVE生成 RDB 快照并发送给从节点,同时记录快照期间的写命令到缓冲区。从节点加载 RDB 后,主节点再把缓冲区的增量命令发送给从节点执行,使数据追平。

  • 增量同步:全量同步完成后,主节点后续的每一条写命令都会异步发送给从节点。从节点通过维护复制偏移量 offset 判断数据是否落后。如果连接断开后短时间内重连,并且偏移量仍在主节点的复制积压缓冲区范围内,就可以通过增量同步快速追平,而不需要再次全量复制。

Redis 2.8 之后用PSYNC替代了旧的SYNC,支持断线后的部分重同步;Redis 7.0 之后进一步演化出基于 replication id 的更完整的PSYNC实现。

2. 主从复制有哪些常见问题?

  • 数据不一致:默认是异步复制,主节点写成功后不会等待从节点落盘。如果主节点突然宕机,尚未同步到从节点的数据会丢失。

  • 复制风暴:当多个从节点同时向同一个主节点发起全量同步时,主节点需要多次执行BGSAVE、多次传输 RDB,CPU、内存和网络压力巨大。可以通过「级联复制」让部分从节点挂到其他从节点上,减少主节点压力。

  • 循环复制:配置主从时如果拓扑出错,可能出现 A 复制 B、B 又复制 A 的循环,需要谨慎规划主从关系。


七、速查表与总结

主题核心要点
Redis 定位内存数据库,非单纯缓存,单线程事件循环 + IO 多路复用
为什么快内存、高效数据结构、单线程、IO 多路复用、Reactor 模型
数据类型String、Hash、List、Set、ZSet + BitMap、HyperLogLog、GEO、Stream
底层结构SDS、QuickList、Dict、IntSet、SkipList、ListPack
过期删除惰性删除 + 定期删除(无定时删除)
内存淘汰noeviction、allkeys/volatile + lru/lfu/random/ttl
RDB快照,恢复快,可能丢最近数据,fork 子进程
AOF追加写命令,everysec 最多丢 1 秒,文件大恢复慢
混合持久化Redis 4.0+,RDB 快照 + AOF 增量,兼顾速度与安全
启动优先级同时存在时优先加载 AOF
缓存穿透缓存空值、布隆过滤器
缓存击穿互斥锁、逻辑过期、永不过期
缓存雪崩过期时间加随机值、多级缓存、限流降级、高可用
缓存一致性先更新数据库再删除缓存、延迟双删、Binlog 订阅
事务MULTI/EXEC/DISCARD/WATCH,不保证回滚原子性
Pipeline批量发送减少 RTT,不保证原子性
Lua服务端原子执行,减少 RTT,可缓存复用
主从复制全量 + 增量,异步复制,可能存在复制风暴

总结:Redis 面试的主线可以浓缩为「基础 → 数据结构 → 持久化 → 过期与淘汰 → 缓存三大问题与一致性 → 事务/Pipeline/Lua → 高可用与集群」。面试回答时,先讲清原理,再结合项目经验说明选型与权衡,这样既能体现深度,也能让面试官相信你真正在生产环境中用过 Redis。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询