运维常见题-Redis维护

目录
本文所引用的核心资料与数据,均由 DeepSeek V4 Flash 辅助生成。为确保内容的可靠性,笔者已对大部分关键论点进行了人工复核与校验。但鉴于大模型的固有局限,本文仍可能存在认知偏差或未尽准确之处。若您在阅读中发现存疑或矛盾之处,欢迎反馈讨论,笔者将及时核实与修正。

🤔 Redis 有哪些应用场景?

  • Redis 作为高性能内存数据库/缓存,应用场景:①缓存(最核心:热点数据加速)②分布式锁(setnx/Redlock)③消息队列/发布订阅(轻量)④计数器/限流(incr)⑤排行榜/最新列表(ZSET/LIST)⑥会话共享(Session)⑦延迟任务/布隆过滤器等。核心:Redis 适合"高性能 + 简单数据结构"的场景,不适合海量存储/强一致事务。

    • ① 缓存(最核心)
      • 热点数据缓存:降低数据库压力、加速读取(最常见场景)
      • 缓存模式:Cache Aside(旁路)/穿透/击穿/雪崩防护
    • ② 分布式锁
      • SETNX + 过期时间 实现锁(多个服务竞争锁)
      • 进阶:Redlock(多节点锁,防单点)
    • ③ 消息队列/发布订阅
      • LIST(阻塞队列)/Pub/Sub(发布订阅)——轻量 MQ(可靠场景用专业 MQ)
    • ④ 计数器/限流
      • INCR 原子自增(计数器:点击量/库存);限流(令牌桶/滑动窗口)
    • ⑤ 排行榜/最新列表
      • ZSET(有序集合):排行榜、按分数排序
      • LIST:最新列表(时间线)
    • ⑥ 会话共享(Session)
      • 多台应用共享 Session(登录态),Redis 存会话
    • ⑦ 其他
      • 延迟任务(生产用 ZSet:score=时间戳,过期 key 通知不可靠仅限非严格场景)、布隆过滤器(缓存穿透)、分布式 ID、位图(签到/统计)
    • 适用边界
      • 适合:高并发读/简单数据结构/要求低延迟
      • 不适合:海量数据(内存贵)、强一致事务(Redis 非事务强一致)、复杂查询
  • 协助记忆

    • Redis 场景口诀:“缓存加速、锁防并发、队列解耦、计数器、排行榜、Session 共享”。
    • 一句话:“高性能简单数据结构的场景用 Redis,复杂/海量/强一致交给 DB”。
  • 进阶思考

    • 缓存穿透、击穿、雪崩分别是什么(高频面试)?
      • 穿透:查不存在的数据(缓存没有+DB 也没有)→ 每次都打 DB。防:布隆过滤器/缓存空值。
      • 击穿:热点 key 过期瞬间大量请求打 DB。防:互斥锁/热点 key 不过期。
      • 雪崩:大量 key 同时过期 → 大量请求打 DB。防:过期时间加随机、多级缓存、限流降级。
    • 为什么 Redis 适合做分布式锁?
      • 原子操作(SETNX + 过期)+ 高性能 + 简单(多服务共享):能实现"同一时刻只有一个服务能拿到锁"。注意:锁要带过期时间(防死锁)、释放要验证(防误删他人锁,用 Lua)。
    • Redis 能当主力数据库吗?
      • 看场景:缓存/简单结构可(Redis 也支持持久化);但海量数据/复杂查询/强事务场景不适合(内存贵、功能不如 DB)。主流定位:“缓存加速层”,数据可靠存储仍靠 DB。
  • 扩展信息

    • Redis 生态周边:Redis 支持模块(BloomFilter/JSON/TimeSeries)、Redis 做缓存 vs 专业 MQ(可靠投递:Kafka/RocketMQ)、版本演进(ACL 权限控制 6.0 引入、Redis Functions 函数 7.0 引入)
    • 缓存一致性模式:Cache Aside(旁路缓存,主流)、Read/Write Through、Write Behind——了解前两者即可(面试常考)
    • Redis 与其他键值存储对比:Memcached(纯缓存无持久化/数据结构单一)、Redis(数据结构丰富+持久化)——Redis 更全能

🤔 Redis 单进程为啥还这么快?

  • Redis 单进程(单线程)仍快的原因:①纯内存操作(内存读写远快于磁盘)②I/O 多路复用(单线程高效处理大量连接)③高效数据结构(底层为专门优化的结构)④避免锁开销/线程切换(单线程无竞争)⑤非阻塞 I/O + 事件循环。核心:“内存快 + 多路复用不浪费 + 单线程无锁开销”。

    • ① 纯内存操作(根本)
      • 数据在内存(读写 ns 级,远快于磁盘 ms 级)——速度快的基础
      • 持久化(BGSAVE/AOF everysec 等后台路径)异步,不阻塞主流程(SAVE 同步/AOF always 会阻塞,需避免)
    • ② I/O 多路复用(高并发关键)
      • 单线程用 epoll(Linux 多路复用)同时监听大量连接
      • 多个连接事件轮询处理(非阻塞 I/O),不用每连接一个线程
      • 处理大量并发连接的能力(数万 QPS 的前提)
    • ③ 高效数据结构(底层优化)
      • 每种数据类型底层用专门结构(SDS 动态字符串、跳表、压缩列表等)
      • 操作大多 O(1)/O(log n),高效
    • ④ 单线程无锁/无切换开销
      • 单线程避免:锁竞争(多线程要加锁)、线程上下文切换开销
      • 命令串行执行(天然线程安全,无需锁)
    • ⑤ 事件循环模型
      • 单线程事件循环:接收事件(连接/命令)→ 依次处理
      • 非阻塞(处理快的命令不拖慢其他)
    • 注意(单线程的代价)
      • 单条命令耗时长会阻塞其他命令(慢命令/大 key/KEYS * 是坑)
      • 6.0 引入多线程处理网络 I/O(但命令执行仍是单线程)
  • 协助记忆

    • 单线程快 = “内存快(基础)+ 多路复用(不浪费)+ 无锁(无开销)"。
    • 一句话:“内存里的操作本来就快,多路复用让它能扛高并发,单线程免了锁的开销”。
  • 进阶思考

    • 为什么单线程反而不比多线程慢(甚至更快)?
      • 多线程有锁竞争/上下文切换/CPU 缓存失效开销;Redis 命令简单(内存操作极快),单线程串行足够快,且避免了这些开销。Redis 瓶颈常在网络/内存而非 CPU(单线程 CPU 不是瓶颈)。
    • 什么操作会让 Redis “卡”(阻塞单线程)?
      • 慢命令:KEYS *(全键扫描)、SMEMBERS 大集合、大 key 操作、SAVE(同步持久化)、BGREWRITEAOF 大文件、删除大 key(新版异步删除 UNLINK 解决)。生产要避免这些(或异步化)。
    • 6.0 多线程改了什么(不是全多线程)?
      • 6.0 用多线程处理"网络 I/O”(读/写 socket),但命令执行仍是单线程——多线程加速了网络吞吐(尤其大并发连接),命令处理逻辑不变(保持简单/无锁)。多线程 I/O 是可配置的(io-threads)。
  • 扩展信息

    • I/O 多路复用对比:select/poll/epoll(Linux epoll 最高效,事件驱动)——理解"单线程如何高并发"的关键
    • Redis 数据结构底层(简单了解):SDS(字符串)、链表/压缩列表、跳表(ZSET)、哈希表——每个数据类型有专门底层实现(高效)
    • 异步删除UNLINK(异步删大 key)/FLUSHALL ASYNC——4.0 引入,解决大 key 删除阻塞

🤔 Redis 支持哪些数据类型?

  • Redis 支持的数据类型:①String(字符串)②List(列表)③Hash(哈希)④Set(集合)⑤ZSet(有序集合)⑥Bitmap(位图)⑦HyperLogLog(基数统计)⑧GEO(地理位置)⑨Stream(流,7.0 起)。核心:五大数据类型(String/List/Hash/Set/ZSet)必答,其余按场景补充。

    • 五大基础类型(必答)
      • String(字符串):最基础,存字符串/数字/JSON;命令 GET/SET/INCR
      • List(列表):有序列表,可做队列/栈/时间线;LPUSH/RPUSH/LRANGE
      • Hash(哈希):键值对集合(对象存储:用户信息);HSET/HGET/HGETALL
      • Set(集合):无序不重复,做去重/交集并集;SADD/SMEMBERS/SINTER
      • ZSet(有序集合):带分数排序的集合,做排行榜/优先级;ZADD/ZRANGE/ZRANK
    • 高级类型(按需补充)
      • Bitmap(位图):位操作(签到/在线状态/统计);SETBIT/GETBIT/BITCOUNT
      • HyperLogLog(基数统计):去重计数(UV 统计,误差小省内存);PFADD/PFCOUNT
      • GEO(地理位置):经纬度存储/距离计算;GEOADD/GEODIST
      • Stream(流):消息流(5.0 引入,7.0 增强消费者组/ACK);XADD/XREAD
    • 场景对应
      • String:缓存/计数器;List:队列/时间线;Hash:对象/会话
      • Set:去重/标签;ZSet:排行榜/排序;Bitmap:签到/位图统计
      • HyperLogLog:UV;GEO:附近的人;Stream:消息
    • 命令前缀记忆
      • 类型命令前缀:String(GET/SET)、List(L开头)、Hash(H)、Set(S)、ZSet(Z)、Bitmap(BIT)、HLL(PF)、GEO(GEO)、Stream(X)
  • 协助记忆

    • 五大类型口诀:“字符串(String)、列表(List)、哈希(Hash)、集合(Set)、有序集合(ZSet)"。
    • 命令前缀记忆:“L 列表、H 哈希、S 集合、Z 有序、BIT 位、PF 基数、X 流”。
  • 进阶思考

    • 各类型底层数据结构(面试加分)?
      • String→SDS;List→快速列表;Hash→哈希表/压缩列表;Set→整数集合/哈希表;ZSet→跳表+哈希表——了解"为什么快/内存省”(底层为场景优化的结构)。
    • String 存对象和 Hash 存对象怎么选?
      • String(JSON 整体存):简单、整体读写(适合不常改部分字段的对象);Hash(字段独立):可只改某字段(适合常改字段、省内存——大对象 Hash 更省)。按"是否常改部分字段"选。
    • ZSet 的"分数"能做什么(不止排行榜)?
      • 分数可做:排行榜(分数=得分)、延迟任务(分数=时间戳)、优先级队列、限流(分数=时间窗口)。“有序 + 按分数操作"让它很灵活。
  • 扩展信息

    • 底层数据结构速查:SDS(字符串)、quicklist(列表)、listpack/ziplist(紧凑)、intset(整数集合)、skiplist(跳表,ZSet)、dict(哈希表)——面试常问"Redis 快/省内存的底层"题
    • 类型 vs 底层:数据类型(逻辑)≠ 底层结构(物理),Redis 按数据规模自动选择底层(如 listpack vs hashtable)
    • 进阶能力:Lua 脚本(原子多命令)、Pipeline(批量)、事务(MULTI/EXEC)——组合数据类型做复杂逻辑

🤔 Redis 内存回收(淘汰)策略有哪些?

  • Redis 内存回收分两类:①过期删除策略(key 到期的处理)②内存淘汰策略(内存满时删哪些 key)。核心:①过期删除:惰性删除 + 定期删除(主动+被动结合);②内存淘汰:maxmemory-policy 配置(noeviction/allkeys-lru/volatile-lru 等),生产一般用 allkeys-lruvolatile-lru

    • ① 过期删除策略(key 到期怎么删)
      • 惰性删除:key 被访问时检查是否过期,过期则删(省资源,但过期 key 可能占内存)
      • 定期删除:定期(每 100ms)抽样检查部分过期 key 删除(主动清理)
      • 结合:惰性(被动)+ 定期(主动)——折中(不实时全删,但避免堆积)
    • ② 内存淘汰策略(内存满时 maxmemory-policy)
      • noeviction(默认):内存满不淘汰,会导致内存增长的写命令报错(DEL/UNLINK 等删除类命令仍允许)
      • allkeys-lru:所有 key 按 LRU(最少最近使用)淘汰——生产常用
      • volatile-lru:仅设了 TTL 的 key 按 LRU 淘汰(无 TTL 的 key 不参与;若都无 TTL 则该策略退化为不淘汰)
      • allkeys-random/volatile-random:随机淘汰(所有/仅设 TTL 的 key)
      • volatile-ttl:按剩余 TTL 短的淘汰(仅设 TTL 的 key)
      • allkeys-lfu/volatile-lfu:按 LFU(最少使用频率)淘汰(Redis 4.0+)
    • 怎么配置
      • maxmemory(内存上限,如 2gb)+ maxmemory-policy(策略)
      • 生产:设 maxmemory(防内存无限涨)并选淘汰策略
    • 选择建议
      • 缓存场景:allkeys-lru(淘汰不常用 key,保留热点)或 volatile-lru(只对有过期时间的 key 淘汰)
      • 不能丢数据(如持久化重要):noeviction(满了报错,人工处理)但会影响业务
  • 协助记忆

    • 内存回收两件事:“过期删除(惰性+定期)“与"内存淘汰(maxmemory-policy)"。
    • 策略口诀:“noeviction 不淘汰(报错)、LRU 少用淘汰、LFU 频用保留”。
  • 进阶思考

    • 惰性删除和定期删除为什么"结合"用?
      • 只惰性:过期 key 不被访问就永远占内存(堆积);只定期:每次要扫很多(开销大)。惰性(被访问才删)+ 定期(周期抽扫):主动清掉不活跃的过期 key,又不大开销——折中方案。
    • LRU 和 LFU 区别(怎么选)?
      • LRU(最近最少使用):看"多久没被访问”(适合缓存:不常用淘汰);LFU(最不经常使用):看"访问频率”(适合:频率低淘汰,防"偶尔访问一次的热点被误淘汰”)。一般缓存用 LRU 够,需抗"突发访问"用 LFU。
    • 为什么生产一定要设 maxmemory?
      • 不设 = 内存无限增长:数据一直加,内存耗尽 → OOM(进程被系统杀)或无限 swap(性能崩)。设 maxmemory + 策略:内存满时"有策略地淘汰"(可控),而非系统崩溃。
  • 扩展信息

    • 内存淘汰与过期删除的关系:过期 key 先被"过期删除"处理;“内存淘汰"是内存满时对未过期 key 的处理(两者独立)
    • LRU 实现:Redis 的 LRU 是"近似 LRU”(抽样 5 个取最久,非全量),兼顾效率与效果
    • 相关命令CONFIG GET maxmemory/INFO memory(看内存)、keyspace 监控

🤔 Redis 两种持久化 RDB 和 AOF 有什么区别及优缺点?

  • Redis 持久化两种:RDB(快照)和 AOF(追加日志),区别:①RDB 存"某一时刻的数据快照"(二进制,恢复快、体积小,但可能丢最后一次快照后的数据);②AOF 存"每一条写命令"(文本,数据更完整,但文件大、恢复慢)。核心:“RDB 快照省空间快恢复但丢数据,AOF 全量命令不丢但开销大”;生产常用两者结合(RDB 快照 + AOF 增量),7.0 起 AOF 合并为单一文件。

    • RDB(快照持久化)
      • 存什么:某一时刻的数据库快照(二进制文件 dump.rdb
      • 触发:SAVE(同步)/BGSAVE(后台异步)/配置自动(save 900 1 等)
      • 优点:①文件小(二进制压缩)②恢复快(直接加载快照)③性能影响小(BGSAVE 后台 fork)
      • 缺点:①可能丢数据(快照间隔间的写会丢,如 5 分钟一次丢 5 分钟)②BGSAVE fork 消耗内存/大实例 fork 慢
    • AOF(追加日志)
      • 存什么:每一条写命令(追加到 appendonly.aof
      • 触发:按策略刷盘(appendfsync always/everysec/no
      • 优点:①数据完整(按策略最多丢 1 秒/不丢)②可读/可修复(文本命令)
      • 缺点:①文件大(所有命令累积)②恢复慢(重放所有命令)③写性能影响(要刷盘)
    • 对比
      维度RDBAOF
      存储快照(数据)命令日志
      体积大(可重写)
      恢复
      丢数据可能(间隔间)少(按策略)
      写性能略差(刷盘)
    • 7.0 AOF 变化
      • AOF 改为"多部分 AOF"(manifest + base/incr 段),对外呈现单一逻辑文件;自动 rewrite(auto-aof-rewrite-*)早于 7.0 已有
    • 最佳实践(结合使用)
      • 生产:RDB(快照备份/快速恢复)+ AOF(增量不丢)——两者结合
      • 另:混合持久化(aof-use-rdb-preamble,AOF 文件含 RDB 头做基础,启动加载快;7.0 起默认开启)——是"RDB 头 + AOF 增量"的文件格式,与"RDB 和 AOF 双开"是两个概念
  • 协助记忆

    • 对比口诀:“RDB 快照(小/快/丢间隔数据)、AOF 日志(全/重/少丢),生产结合用”。
    • 一句话:“想省心用 RDB 快恢复,想不丢用 AOF 全记录,最好两个都要”。
  • 进阶思考

    • 为什么 RDB 会丢数据?怎么减少?
      • RDB 是"定时快照":两次快照之间的写不落盘,进程挂/断电丢这段时间数据。减少:缩短快照间隔(如 save 60 1000)或用 AOF 补增量。要更不丢用 AOF。
    • AOF 文件越来越大怎么办(rewrite)?
      • AOF 累积所有命令 → 文件大、恢复慢 → AOF rewriteBGREWRITEAOF):重写成"当前数据的最新命令"(瘦身)——7.0 自动管理(单一文件)。生产要定期/自动 rewrite。
    • Redis 持久化和"缓存数据丢了无所谓"矛盾吗?
      • 不矛盾:Redis 可纯缓存(重启丢缓存,从 DB 重建)也可持久化(数据重要才持久化)。生产常"Redis 持久化开启"(防重启全丢缓存/避免缓存雪崩重建风暴)。按数据重要性决定持久化强度。
  • 扩展信息

    • 持久化配置save(RDB 触发)、appendonly yes/appendfsync(AOF 开关/刷盘)、auto-aof-rewrite-*(自动重写)
    • 混合持久化(4.0+):RDB 做基础快照 + AOF 做增量(重启加载快+RDB 后重放 AOF)——两者结合的优势,生产推荐
    • 数据恢复:重启时若配置持久化,自动从 RDB/AOF 加载(有 AOF 优先 AOF——更全);备份用 RDB/AOF 文件 + 定期备份
      • 运维:INFO persistence 看持久化状态、redis-check-aof 修复损坏 AOF

🤔 Redis 内存持续飙升,该如何排查?

  • Redis 内存飙升排查:①看内存统计(INFO memory/redis-cli --stat)②分析内存构成(MEMORY USAGE/MEMORY DOCTOR/大 key)③定位原因(数据增长/大 key/碎片/过期 key 堆积/内存淘汰未生效)④解决(删大 key/优化数据结构/设 maxmemory+淘汰/碎片整理/过期清理)。核心:“先看内存统计→定位大 key/异常→清理与限制”。

    • 第一步:看内存统计
      • INFO memoryused_memory(实际使用)、used_memory_humanused_memory_rss(进程占用,含碎片)
      • used_memory_rss 远大于 used_memory → 内存碎片
      • redis-cli --stat(实时看内存/QPS)
    • 第二步:定位大 key/内存大户
      • MEMORY USAGE <key>(单 key 内存)、MEMORY DOCTOR(诊断建议)
      • 大 key 扫描:redis-cli --bigkeys(找大 key)
      • KEYS * 不推荐(阻塞),用 SCAN 遍历
      • 按类型看:Hash/List/ZSet 大集合是内存大户
    • 第三步:分析原因(为什么会涨)
      • 数据持续写入(业务增长/缓存未过期)
      • 大 key(单 key 内存巨大:大 List/Hash/字符串)
      • 内存碎片(mem_fragmentation_ratio 高:增删多导致)
      • 过期 key 堆积(惰性删除没清、定期删除慢)
      • 未设 maxmemory(无限增长,最终 OOM)
      • 慢命令/连接数(连接也占内存)
    • 第四步:解决
      • 删大 keyUNLINK(异步删除,不阻塞)、拆分大 key(数据分片)
      • 设 maxmemory + 淘汰策略:防无限增长(allkeys-lru 等)
      • 过期清理:调定期删除频率/检查过期 key 是否堆积
      • 碎片整理memory purge/activedefrag(自动碎片整理,4.0+)
      • 优化数据结构:压缩/精简(如 Hash 用 field 而非多个 String)
      • 容量:必要时扩容/数据分层(冷数据落 DB)
  • 协助记忆

    • 内存排查口诀:“INFO 看统计、MEMORY 查大户、找大 key(bigkeys)、设 maxmemory、清碎片/过期”。
    • 一句话:“先看数据还是碎片,再定位大 key/未限制,删/限/清”。
  • 进阶思考

    • 内存碎片怎么来的?怎么解决?
      • 频繁增删数据(内存分配/释放不连续)→ 碎片(used_memory_rss > used_memory)。解决:activedefrag yes(自动碎片整理)或重启(清碎片)、memory purge(手动)。碎片严重会导致 RSS 涨但数据没涨多少。
    • 大 key 为什么危险?
      • ①占内存(单 key 巨大)②操作阻塞(大 key 的 GET/DEL/遍历会卡单线程)③影响其他请求。定位:--bigkeys 扫描 + MEMORY USAGE;删除用 UNLINK(异步)避免阻塞。
    • 没设 maxmemory 会怎样?
      • 内存无限涨 → 系统 OOM(Redis 被杀)或疯狂 swap(性能崩)——Redis 直接不可用。生产必设 maxmemory + 淘汰策略(可控地处理内存满),并监控内存水位(如 80% 告警)。
  • 扩展信息

    • 内存相关命令速查INFO memoryMEMORY USAGE keyMEMORY DOCTORMEMORY PURGEredis-cli --bigkeysCONFIG GET maxmemory
    • 内存优化思路:数据结构精简(Hash 聚合)、设置 maxmemory、过期清理、碎片整理、数据分层(热 Redis/冷 DB)、容量规划
    • 监控水位:内存使用率告警(70%/80%/90% 分级),防 OOM

🤔 使用 Redis INFO 命令查看哪些关键指标?

  • Redis INFO 命令按段返回运行信息,关键指标分几块:①server(版本/运行时间)②memory(内存:used_memory/maxmemory/碎片)③stats(QPS/命中率/连接/keyspace)④clients(连接数)⑤persistence(持久化状态)⑥replication(主从状态)⑦cpu(CPU 使用)。核心:监控内存、命中率、连接、持久化、主从几个关键段。

    • INFO 分段说明
      • INFO(全部)/INFO memory(只某段)/INFO server
    • 关键段与指标
      • memory(内存,最关键)used_memory(使用内存)、used_memory_humanused_memory_rss(进程内存,看碎片)、mem_fragmentation_ratio(碎片率,结合 used_memory 绝对量级判断:小实例数据量小时碎片率天然偏高,大实例 >1.5 才需关注)、maxmemory(上限)、used_memory_peak(历史峰值)
      • stats(统计)total_connections_received/total_commands_processed(QPS 相关)、keyspace_hits/keyspace_misses(命中/未命中→命中率)、rejected_connections(被拒连接)
      • clients(连接)connected_clients(当前连接)、blocked_clients(阻塞连接)、maxclients(上限)
      • persistence(持久化)rdb_last_bgsave_status(上次保存状态)、aof_enabledaof_last_write_statusaof_rewrite_in_progress
      • replication(主从)role(master/slave)、connected_slaves(从库数)、master_link_status(主从连接)、slave_repl_offset(复制偏移)
      • cpuused_cpu_sys/used_cpu_user(CPU 使用)
      • serverredis_version(版本)、uptime_in_seconds(运行时间)
    • 怎么用(监控)
      • redis-cli info / INFO memory——人工查看
      • 监控采集:redis_exporter(Prometheus)采集 INFO 指标
      • 关键告警:内存、命中率、连接数、主从断开、持久化失败
  • 协助记忆

    • INFO 关键段口诀:“内存(used_memory/碎片)、统计(命中率/QPS)、连接(clients)、持久化(aof/rdb)、主从(role/offset)"。
    • 一句话:“INFO 里盯内存、命中、连接、持久化、主从这五块”。
  • 进阶思考

    • 命中率怎么算(低了说明什么)?
      • 命中率 = keyspace_hits / (keyspace_hits + keyspace_misses)。低命中率 = 大量 key 未命中(缓存没生效/穿透/过期)——说明缓存效率差,要查(数据过期快/穿透)。
    • mem_fragmentation_ratio(碎片率)怎么看?
      • = used_memory_rss / used_memory:>1.5 说明碎片严重(要整理/重启);<1 说明有 swap(内存不足,危险)。正常 1~1.5。
    • 连接数指标怎么用(connected_clients)?
      • 连接数接近 maxclients → 连接耗尽(新连接被拒:rejected_connections 涨)→ 查连接泄漏(客户端没关连接)/连接池不足。监控连接数 + 被拒数告警。
  • 扩展信息

    • INFO 全量段:Server/Clients/Memory/Persistence/Stats/Replication/CPU/Commandstats/Cluster/Keyspace——按需用 INFO <section>
    • 监控工具redis_exporter(Prometheus)、redis-cli --stat、云 Redis 监控(有内置指标)
    • 关键阈值参考:内存 >80% maxmemory 告警、命中率 <90% 关注、碎片率 >1.5 处理、连接接近 maxclients 告警

🤔 简述 Redis 主从复制工作原理?

  • Redis 主从复制(Master-Slave Replication):主库(Master)负责写,从库(Slave/Replica)从主库复制数据,实现读写分离与数据冗余。原理:①全量复制(初次:主库生成 RDB 快照给从库+后续命令)②增量复制(运行中:主库把写命令发给从库同步)③offset/积压缓冲区(断线续传)。核心:“主库写、从库读,全量+增量同步,断线续传”。

    • 作用
      • 读写分离(主写从读,分担读压力)、数据冗余(从库备份)、故障切换基础
    • 全量复制(初次/断线无法增量)
      • 从库连接主库 → 主库 BGSAVE 生成 RDB → 发送给从库 → 从库加载
      • 加载期间主库新写的命令先缓存(replication buffer)→ 加载完补发
      • 适用:初次建立/断线太久(积压缓冲区已覆盖不了)
    • 增量复制(运行中持续)
      • 主库每写一条命令 → 发给从库(propagate)→ 从库执行(保持同步)
      • 依赖:复制偏移量(offset)+ 积压缓冲区(backlog,记录最近命令)
    • 断线续传(部分重同步 PSYNC)
      • 从库断线重连 → 带自己的 offset + master_replid → 主库校验 replid 一致且积压缓冲区还有这些命令
      • 满足 → 从断点增量补发(部分重同步,高效);不满足(offset 超出 backlog 或 replid 不一致/换过复制链)→ 全量重来
    • 关键配置/概念
      • 从库:replicaof <master-ip> <port>(或 SLAVEOF
      • master_replid(复制 ID)、repl_offset(偏移量)、repl-backlog-size(积压缓冲区大小)
      • 主从数据:master_link_status:up/down(连接状态)
    • 注意
      • 默认异步复制(从库可能短暂落后)、从库只读(默认 replica-read-only yes
      • 全量复制对大实例有开销(RDB 生成+传输)
  • 协助记忆

    • 主从复制 = “主库写,从库跟着同步:先全量(快照)+后增量(命令),断线从断点续传”。
    • 口诀:“全量起步、增量持续、offset 续传”。
  • 进阶思考

    • 全量复制和增量复制什么时候用?
      • 初次/长期断线(积压区覆盖不了)→ 全量(RDB 快照+补命令);运行中断线短(积压区还有)→ 增量(从断点补)。增量高效(不重新传全部数据),全量开销大(大实例尽量少触发)。
    • repl-backlog-size(积压缓冲区)设多大?
      • 决定"断线多久还能增量续传”:积压区越大能容忍断线越久(且内存开销越大)。按"网络稳定性 + 写入量"设(写入快/断线久 → 设大些,避免频繁全量复制)。
    • 主从复制会不会丢数据?
      • 默认异步:主库写完可能还没同步到从库,主库挂 → 从库缺最近写入(短暂丢)。注意:哨兵/Cluster 的故障转移仍是异步复制(只降低故障影响,不保证不丢);真正提供"写确认"语义的是 WAIT/同步复制(但性能降)。“异步默认 + 可配更可靠”。
  • 扩展信息

    • 命令REPLICAOF/SLAVEOF(设置主从)、INFO replication(看状态)、redis-cli --replicaof
    • 复制类型:全量同步(RDB)、增量同步(命令流)、部分重同步(offset 断点续传)——三类
    • 演进REPLICAOF 命令/replicaof 配置自 Redis 5.0 起启用(SLAVEOF 降为别名);INFO replicationconnected_slaves/slave_repl_offset 字段当前版本仍用 slave 命名(官方术语迁移尚未完成)

🤔 Redis 主从复制延迟过高怎么解决?

  • Redis 主从复制延迟(从库数据滞后于主库)原因:①网络延迟/带宽(主从传输慢)②从库处理慢(大命令/从库负载高)③主库写入量大(同步跟不上)④积压缓冲区太小(触发全量)。解决:网络优化、减从库负载、repl-backlog-size 调大、主库写入分担、监控延迟。

    • 常见原因
      • 网络:主从跨机房/带宽不足(传输慢)
      • 从库负载高:从库跑重查询/慢命令(处理命令慢)
      • 主库写入量大:写命令多,同步跟不上
      • 大命令/大 key:单条命令复制慢(大 key 传输)
      • 积压缓冲区小:断线后无法增量(触发全量复制,更慢)
      • 同步复制写阻塞:配了 WAIT 等从库确认——增加的是主库写响应延迟(与“从库滞后”机理不同,属写延迟口径)
    • 查看延迟
      • INFO replication:看 master_repl_offsetslave_repl_offset 差(偏移量差 = 滞后量)、slave_repl_lag
      • 注:redis-cli --latency 测的是客户端→服务端 RTT,非主从复制滞后,勿混用
    • 解决方法
      • 网络优化:主从同机房/同区域、带宽充足、专线
      • 从库减负:从库别跑重查询(或加只读副本)、别让从库做持久化太重
      • 积压缓冲区调大repl-backlog-size 调大(减少全量复制)
      • 主库写入分担:主库写压力大 → 分片(Cluster)/应用优化
      • 避免大命令/大 key:拆大 key(复制快)
      • 监控延迟:偏移量差告警(超过阈值处理)
    • 核心
      • 复制延迟是"同步速度跟不上写入速度":要么加快同步(网络/从库),要么减少写入(分片),要么允许一定延迟(异步本质)
  • 协助记忆

    • 延迟解决口诀:“网络优化(同机房)、从库减负、backlog 调大、主写分片、避免大 key”。
    • 一句话:“同步跟不上了就提速(网络/从库)或减量(分片/去大key)"。
  • 进阶思考

    • 怎么"量化"复制延迟(不只看感觉)?
      • 对比 master_repl_offset(主库)和 slave_repl_offset(从库)差值 → 主从数据差多少(字节/命令数);再换算时间(写入速率)。持续监控偏移差告警。
    • 为什么"大 key"会加剧复制延迟?
      • 大 key 的操作(如大集合增删)产生大命令/大量数据:主库执行快、复制传输/从库执行慢 → 从库被这个大命令拖住(滞后)。避免大 key 或拆小。
    • 复制延迟对业务影响?能不能容忍?
      • 影响:从库读到旧数据(读一致性);故障切换时丢最近写(主挂切从,缺延迟数据)。容忍度看业务(读延迟敏感/写重要)——严格场景用半同步/WAIT;Cluster 降低丢写靠 min-replicas-to-write 配置。
  • 扩展信息

    • 延迟相关master_repl_offset/slave_repl_offset(偏移差)、INFO replication、积压缓冲区(backlog)
    • 主从架构演进:主从复制 → 哨兵(加自动故障切换)→ Cluster(分片+副本)——延迟/高可用逐步增强
    • 读一致性取舍:异步复制(从库可能旧)vs 半同步(WAIT 保证不丢但慢)——按业务权衡

🤔 Redis 高可用方案有哪些?

  • Redis 高可用方案(由简单到复杂):①主从复制(基础:数据冗余/读写分离,但主库故障需手动切换)②哨兵模式 Sentinel(在主从基础上加自动故障切换/监控,生产标配)③Redis Cluster(分片+副本+自动故障转移,支持大数据量/多节点)。核心:“主从是基础,哨兵加自动切换,Cluster 加分布式扩展”。

    • ① 主从复制(基础高可用)
      • 主写从读(读写分离)+ 数据冗余(从库备份)
      • 局限:主库故障不会自动切换(需人工 promote 从库)——不算完整高可用
      • 适用:读写分离/简单冗余(故障切换容忍人工)
    • ② 哨兵模式(Sentinel,生产标配高可用)
      • 在主从基础上加 Sentinel(哨兵):监控主从、自动故障转移、通知客户端
      • 主库故障 → 哨兵自动选新主(从库 promote)+ 客户端感知
      • 优点:自动故障切换(秒级~分钟级)、无需人工
      • 适用:中小规模需要自动高可用(单主多从)
      • 局限:单主写(写无扩展)
    • ③ Redis Cluster(分布式高可用)
      • 分片(多主节点各自管数据)+ 副本 + 自动故障转移
      • 优点:写扩展(多主分片)+ 高可用(副本自动切换)+ 大数据量(水平扩展)
      • 适用:大数据量/高写入/多节点集群
      • 局限:运维复杂、跨槽操作受限(多 key 操作要在同槽)
    • 选型
      • 简单冗余:主从;自动高可用(中小):哨兵;大数据量/扩展:Cluster
      • 云 Redis:云厂商托管(自带高可用,省心)
  • 协助记忆

    • 高可用三档:“主从(基础冗余)→ 哨兵(自动切换)→ Cluster(分布式扩展)"。
    • 一句话:“要自动切换用哨兵,要扩展用 Cluster,简单冗余用主从”。
  • 进阶思考

    • 哨兵和 Cluster 怎么选(核心区别)?
      • 哨兵:单主多从(一个写节点,自动切换主)——适合"写不大/数据量适中"需要高可用;Cluster:多主分片(多写节点)——适合"写大/数据多"需要扩展。哨兵解决"高可用”,Cluster 解决"高可用+扩展”。
    • 哨兵集群本身怎么保证高可用?
      • Sentinel 也要多节点(一般 3+,奇数):多个哨兵互相监控 + 投票决定故障(防单哨兵误判)。哨兵数要"多数派"(3 节点容忍 1 故障)——哨兵不是单点。
    • 高可用方案的"故障切换会丢数据吗"?
      • 取决于复制模式:异步复制下主库挂 → 切换的新主可能缺最近未同步数据(短暂丢)。要更可靠:WAIT/半同步或 Cluster 的副本多数派——权衡可用性与一致性。
  • 扩展信息

    • 高可用方案对比:主从(人工切换)、哨兵(自动切换,单写)、Cluster(分片+自动,多写)、云 Redis(托管高可用)
    • 哨兵 vs Cluster 演进:Redis 官方推荐大数据量/生产用 Cluster;哨兵适合中小/已有主从架构升级
    • 故障切换代价:切换有秒级~分钟级不可用窗口(哨兵检测+选主)、数据可能短暂丢失(异步)——高可用方案是"权衡"非"完美""

🤔 什么是 Redis 哨兵模式 (Sentinel)?

  • Redis 哨兵模式(Sentinel)是在主从复制基础上加"哨兵进程"实现自动高可用:哨兵监控主从状态,主库故障时自动选新主(提升从库)并通知客户端。核心:“哨兵 = 监控 + 自动故障转移 + 通知”,实现 Redis 主从的自动切换(无需人工)。

    • 是什么(定义)
      • 在主从(Master-Replica)基础上部署 Sentinel 进程(哨兵)
      • 哨兵职责:监控(主从健康)、自动故障转移(主挂选新主)、通知(告知客户端新主)
      • 解决主从"主库挂了不会自动切换"的问题(人工切换)
    • 哨兵核心功能
      • 监控:定期 ping 主从(判断存活)
      • 故障转移(Failover):主库故障 → 选一个从库提升为新主 → 其他从库改从新主
      • 通知:把新主信息告诉客户端/其他哨兵
      • 配置提供:客户端可从哨兵获取当前主节点
    • 工作原理(故障转移流程)
      1
      2
      3
      4
      5
      
      1. 哨兵监控主库(ping 心跳)
      2. 主库不可达 → 哨兵标记主观下线(sentinel 主观判断)
      3. 多个哨兵确认 → 客观下线(quorum 配置确认,防误判;触发转移还需哨兵间 majority 选举 leader)
      4. 哨兵 leader 按规则(优先级/偏移量/runid)选定从库 → 提升为新主(promote;从库按规则选定,非投票产生)
      5. 其他从库改从新主、通知客户端 → 高可用恢复
    • 哨兵集群(自身高可用)
      • Sentinel 多节点部署(3+,奇数):互相监控 + 投票(多数派决策,防单哨兵误判)
      • 哨兵挂了不影响已运行的主从(但故障转移依赖哨兵存活)
    • 配置
      • sentinel monitor <master-name> <ip> <port> <quorum>(定义监控的主)
      • sentinel.conf(哨兵配置)
    • 与主从区别
      • 主从:数据复制(无自动切换);哨兵:主从 + 自动故障转移(高可用)
  • 协助记忆

    • 哨兵 = “主从的自动管家”:看着主从(监控),主挂了自动换(选新主),并告诉大家(通知)。
    • 口诀:“监控 + 自动故障转移 + 通知,主挂秒换新主”。
  • 进阶思考

    • 哨兵怎么判断主库"真挂了"(防误判)?
      • 单哨兵标记主观下线(SDOWN)→ 达到 quorum 数哨兵确认客观下线(ODOWN)→ 哨兵间 majority 选举 leader → 才触发故障转移。防"一个哨兵误判/网络抖动就切换"。
    • 哨兵选新主的依据(怎么选从库)?
      • 官方选主顺序:①slave-priority(数值小优先,0 不参与)②复制偏移量最大(数据最全)③runid 最小。优先选"数据最接近主库"的从库(少丢数据)。
    • 故障转移会丢数据吗?
      • 可能:异步复制下主库挂时未同步到从库的数据丢失(切换的新主缺这部分)。要少丢:WAIT/半同步或接受短暂丢——高可用与数据一致性权衡。
  • 扩展信息

    • 哨兵 vs Cluster(定位):哨兵解决"单主高可用"(一个写节点自动切换);Cluster 解决"多主扩展+高可用"(分片)。中小规模高可用用哨兵,大数据量/扩展用 Cluster。
    • 配置要点quorum(客观下线所需哨兵数)、down-after-milliseconds(判定下线时间)、failover-timeout(转移超时)
    • 演进:Redis 官方趋势——大数据量/新项目更多用 Cluster;哨兵适合已有主从架构/中小规模

🤔 哨兵模式 (Sentinel) 下应用程序如何连接?

  • 哨兵模式下应用连接:不是直连主节点(IP 会因故障切换变化),而是连哨兵(Sentinel)获取当前主节点地址,再连主节点。实现:①客户端用哨兵地址 + master-name,通过 Sentinel API 获取主节点②监听哨兵通知(切换时自动重连新主)③官方客户端(如 Java Redis 客户端)内置 Sentinel 支持。 核心:“应用连哨兵拿主节点,故障切换后自动获知新主”。

    • 为什么不能直连主节点
      • 主节点 IP 会变(故障切换后新主是原来的从库,地址不同)
      • 直连旧 IP → 切换后连不上(服务中断)
    • 应用连接方式(Sentinel 模式)
      • 应用配置:Sentinel 地址(sentinel 节点 IP/端口)+ 主节点名(mymaster
      • 连接流程:应用 → 连任一哨兵 → 问"当前主节点是谁"(SENTINEL get-master-addr-by-name)→ 拿主节点地址 → 连接主节点读写
      • 故障切换:哨兵通知/客户端重新查询 → 应用自动连到新主(无需改配置)
    • 客户端支持
      • 主流客户端内置 Sentinel:Java(Jedis/Lettuce)、Python(redis-py)、Go(go-redis)等
      • 配置方式:客户端传入 Sentinel 节点列表 + masterName(如 Jedis JedisSentinelPool
    • 示例(概念)
      1
      2
      3
      4
      
      // Jedis Sentinel 配置(概念)
      Set<String> sentinels = { "sentinel1:26379", "sentinel2:26379" };
      JedisPool pool = new JedisSentinelPool("mymaster", sentinels);
      // 获取连接时 Jedis 会向哨兵查询当前主节点
    • 核心
      • 应用"面向哨兵 + 主节点名",不面向具体 IP——故障切换对应用透明(自动重连新主)
  • 协助记忆

    • 哨兵连接 = “应用问哨兵’主在哪’(master-name),哨兵告诉它,切主后自动换”。
    • 一句话:“连哨兵拿主节点,别写死 IP,切换自动适应”。
  • 进阶思考

    • 为什么用"master-name"而不是 IP?
      • IP 会变(切换后新主地址不同);master-name(如 mymaster)是逻辑名:哨兵知道"mymaster 当前对应哪台"——应用只认名字,地址由哨兵动态给(解耦)。
    • 故障切换时应用会中断吗?
      • 会短暂中断(切换期间旧主不可用、新主提升有秒级窗口):客户端会报错/超时,切换完成后自动连新主恢复。应用要做重试/连接池,接受短暂中断(哨兵高可用是"秒级切换"不是"零中断")。
    • 哨兵本身怎么连(应用配置多个哨兵)?
      • 应用配多个哨兵地址(哨兵集群):一个哨兵挂了连其他——哨兵本身高可用(多数派)。应用连任意一个能用的哨兵即可拿到主节点信息。
  • 扩展信息

    • 哨兵相关命令SENTINEL get-master-addr-by-name <name>(查主)、SENTINEL masters(看主列表)、SENTINEL monitor(配置)
    • 客户端配置:Sentinel 节点列表 + masterName(主流客户端均支持);切换后客户端自动重连(客户端内置订阅哨兵通知/重新查询)
    • 与 Cluster 连接对比:哨兵(面向 master-name 连单主);Cluster(面向任一节点,客户端用 cluster 协议路由到分片)——连接方式不同

🤔 简述 Redis Cluster 工作原理?

  • Redis Cluster 是分布式集群:把数据按"槽位(16384 个 slot)“分片到多个主节点(每个主节点管一段槽),客户端按 key 哈希路由到对应节点,每个主节点可有副本(从节点)实现高可用,主节点故障自动转移到副本。核心:“槽位分片 + 客户端路由 + 副本自动故障转移”,实现写扩展与高可用。

    • 核心概念
      • 槽位(Slot):16384 个槽(0~16383),数据按 key 的 CRC16 哈希对 16384 取模分到某槽
      • 主节点分片:每个主节点负责一段槽(如 3 主节点各 5000+ 槽)——数据分布在不同节点
      • 副本(Replica):每个主节点可有从节点(副本)备份 + 故障接管
    • 工作原理
      1
      2
      3
      4
      
      1. 写 key → 计算 key 的槽(CRC16(key) % 16384)→ 定位负责该槽的主节点
      2. 客户端连对节点:若连错(槽在其他节点)→ 返回 MOVED 重定向 → 客户端跳到正确节点
      3. 主节点有副本:主挂 → 副本自动提升为新主(故障转移)
      4. 客户端按槽路由(cluster 客户端内置槽-节点映射)
    • 关键机制
      • CRC16 哈希槽:key 定位槽(HASH_SLOT = CRC16(key) % 16384
      • MOVED/ASK 重定向MOVED = 槽归属已变的永久重定向(客户端须更新并缓存槽映射,再访问);ASK = 槽迁移中的临时重定向(仅对单条命令有效、不缓存,需先发 ASKING)——两者语义不同勿混
      • 故障转移:主节点故障(多数派确认)→ 从副本提升为新主(类似哨兵机制,Cluster 内置)
      • 集群总线(cluster bus):节点间通信(gossip 传播状态)
    • 数据访问注意
      • 多 key 操作(MGET/MSET 跨槽)会失败——除非用 hash tag({user} 相同标签同槽)
    • 部署
      • 至少 3 主节点(生产 3 主 + 每主副本,如 6 节点)
      • 端口:客户端端口 + 10000 = 集群总线端口(如 7000→17000,bus 端口默认 +10000)
  • 协助记忆

    • Cluster = “槽位分片”:16384 槽按 key 哈希分到多主,客户端按槽路由,副本自动接管故障。
    • 口诀:“CRC16 分槽、MOVED 路由、副本故障转移、多 key 要同槽(hash tag)"。
  • 进阶思考

    • 为什么用"16384 个槽”(不是无限分)?
      • 固定槽数(16384)便于:槽-节点映射(节点增减只需迁移槽,不用全量重hash)、路由信息小(心跳带槽位图)。16384 是兼顾"分片粒度"和"路由信息大小"的平衡。
    • MOVED 重定向是什么(客户端怎么应对)?
      • 客户端请求的槽不在该节点 → 返回 MOVED <slot> <ip:port> 指向正确节点——客户端缓存槽-节点映射后直接访问(不用每次重定向)。集群客户端(cluster 模式)内置该逻辑。
    • Cluster 的"多 key 操作"为什么受限?
      • 多 key 在不同槽(不同节点)就无法原子操作(如 MGET 跨节点)。解决:hash tag({user}:orders{user}:cart{user} 同槽)——把相关 key 放同槽。设计时注意。
  • 扩展信息

    • Cluster 与哨兵/主从对比:主从(单写)、哨兵(单写+自动切换)、Cluster(多写分片+自动故障)——规模/扩展递增
    • 哈希槽 vs 一致性哈希:Cluster 用固定槽(CRC16%16384),与 Memcached 一致性哈希不同(固定槽迁移/路由更可控)
    • 常用命令CLUSTER INFO/CLUSTER SLOTS(看槽分布)、redis-cli -c(集群模式自动重定向)

🤔 Redis Cluster 集群不可用的常见原因及解决方案?

  • Redis Cluster 不可用原因:①槽分配不均/槽迁移失败②主节点故障且无可用副本(副本不足)③多数派节点故障(无法选出新主)④网络分区(脑裂/节点失联)⑤客户端路由问题(连错/MOVED 没处理)⑥配置错误(槽覆盖/重复)。解决:槽均衡/迁移修复、保证副本数、检查多数派/网络、客户端用集群模式、配置校验。

    • ① 槽问题(槽迁移/分配)
      • 槽分配不均(部分节点槽多压力大);槽迁移中(CLUSTER SETSLOT/reshard 失败)
      • 槽没覆盖全(16384 槽未分配全 → 部分数据无主)
      • 解决:CLUSTER RESHARD(重新分槽)、检查槽覆盖(CLUSTER INFOcluster_state
    • ② 主节点故障无副本
      • 主节点挂了但无可用副本(副本也挂了/没配副本)→ 该主节点的槽不可用
      • 解决:每主配副本(cluster-require-full-coverage 权衡)、补副本
    • ③ 多数派节点故障
      • 集群多数派节点不可达 → 无法选出新主(故障转移需多数派确认)
      • 解决:保证集群多数派存活(容量/故障隔离)、快速恢复节点
    • ④ 网络分区
      • 节点间网络分区:少数派侧无法选举新主(多数派投票防长期双主);真正风险是少数派侧旧主在分区期间接收的写入,愈合后被丢弃(数据丢失)
      • 解决:网络稳定、cluster-node-timeout 合理、监控集群状态
    • ⑤ 客户端路由问题
      • 客户端没用集群模式(连单节点、不处理 MOVED)→ 访问跨节点报错
      • 解决:客户端用 cluster 模式(redis-cli -c/客户端 cluster 支持)
    • ⑥ 配置/部署错误
      • 重复节点、配置不一致(“槽覆盖/两节点管同槽"是极端配置错误,正常 CLUSTER SETSLOT 会拒绝,非常见故障)
      • 解决:检查 CLUSTER NODES/CLUSTER SLOTS,重新初始化(必要时重建集群)
    • 排查命令
      • CLUSTER INFO(集群状态:cluster_state:ok/fail)、CLUSTER NODES(节点/槽/主从)、CLUSTER SLOTS(槽分布)
      • 日志/监控(节点故障、网络、重定向)
  • 协助记忆

    • Cluster 不可用排查口诀:“看 CLUSTER INFO 状态、查槽分布(SLOTS)、检查副本(每主有备)、多数派存活、客户端集群模式”。
    • 一句话:“槽没覆盖/主没副本/多数派挂了/客户端没集群模式——逐个查”。
  • 进阶思考

    • cluster-require-full-coverage 是什么(集群可用性权衡)?
      • 默认 yes:任一槽无主(某主+副本全挂)→ 整个集群拒绝服务(保数据一致,牺牲可用);设 no:有槽不可用但其他正常服务(保可用,部分数据不可访问)。按"一致性 vs 可用性"权衡。
    • 脑裂怎么发生(网络分区)?
      • 网络分区把集群分成两边:两边各自有主节点(互相认为自己是主)→ 写分散(数据分裂)。防:多数派(分区小的一边失去多数派无法提供写)、cluster-node-timeout(超时判死)、监控网络。Cluster 靠多数派 + 超时防脑裂。
    • 槽迁移中请求会怎样?
      • 槽迁移期间:请求可能返回 ASK(迁移中)或 MOVED(已迁完)——客户端处理 ASK/MOVED 重定向(集群客户端内置)。迁移期间服务不中断(但要注意迁移完成确认)。
  • 扩展信息

    • 集群健康检查CLUSTER INFO(cluster_state)、CLUSTER NODES(节点状态/槽)、redis-cli --cluster check(检查集群)、监控(节点数/槽分布/副本数)
    • 运维操作:加节点(redis-cli --cluster add-node)、删节点、RESHARD(重分槽)、故障恢复(副本 promote)
    • 最佳实践:3 主 3 从起步、每主配副本、监控槽覆盖/多数派、客户端集群模式、网络稳定

🤔 Redis 阻塞、卡顿怎么处理?

  • Redis 阻塞/卡顿处理:①定位阻塞源(SLOWLOG 慢命令/LATENCY 延迟/INFO 状态)②常见阻塞源(慢命令 KEYS/大 key 操作/持久化 fork/SAVE 同步/AOF 刷盘/内存 swap/网络)③针对性解决(避免慢命令、拆大 key、异步持久化、调参数)。核心:“先定位卡在哪(慢命令/持久化/内存),再对症(改命令/拆 key/调参)"。*

    • 第一步:定位阻塞
      • SLOWLOG GET(慢命令日志:看哪些命令耗时)
      • LATENCY DOCTOR/LATENCY LATEST(延迟诊断,需先设 latency-monitor-threshold >0 才有数据)
      • INFO statslatest_fork_usec fork 耗时)、INFO commandstats(各命令耗时)
      • 观察(redis-cli --latency/-i 实时)
    • 第二步:常见阻塞源
      • 慢命令KEYS *(全扫描)、SMEMBERS/HGETALL(大集合全取)、SORT 大集合、ZRANGE 大范围——单线程执行耗时,阻塞其他
      • 大 key 操作:大 key 的 GET/DEL(删除大 key 阻塞)/遍历
      • 持久化阻塞SAVE(同步快照阻塞)、BGSAVE 大实例 fork(fork 阻塞)、AOF appendfsync always(每次写刷盘)、BGREWRITEAOF 大 AOF
      • 内存问题:内存 swap(不足时换页极慢)、内存淘汰风暴(满时大量淘汰)
      • 资源耗尽:磁盘 IOPS 打满(持久化写盘/大流量落盘)、CPU 满载(复杂命令/大并发)——整体变慢
      • 网络:客户端慢(输出缓冲大/慢连接)——client-output-buffer-limit
    • 第三步:解决
      • 避免慢命令KEYS *SCAN;大集合分页/增量处理
      • 拆大 key:大 List/Hash 拆分(减少单命令耗时);UNLINK(异步删除大 key)
      • 持久化调优:用 BGSAVE(后台)别用 SAVE;AOF everysec(别 always);BGREWRITEAOF 低峰执行
      • 内存:设 maxmemory + 淘汰策略、检查 swap(加内存)
      • 网络/缓冲:调大客户端输出缓冲/排查慢客户端
      • 监控告警:延迟/慢命令告警(提前发现)
  • 协助记忆

    • 阻塞排查口诀:“SLOWLOG 看慢命令、LATENCY 看延迟、KEYS 换 SCAN、大 key 拆/异步删、SAVE 换 BGSAVE”。
    • 一句话:“单线程最怕慢命令和大 key,持久化别同步,内存别 swap”。
  • 进阶思考

    • 为什么单线程下"一个慢命令"能卡住整个 Redis?
      • 单线程串行执行命令:一条命令耗时 N 秒,后面所有命令都等 N 秒(整库卡顿)。所以慢命令/大 key 是 Redis 大忌(执行时全局阻塞)。
    • 大 key 删除为什么阻塞(UNLINK 解决)?
      • DEL 删除大 key:要遍历释放内存(耗时,阻塞单线程);UNLINK(异步删除):后台释放(不阻塞)——生产删大 key 用 UNLINK。
    • BGSAVE fork 为什么会阻塞?
      • BGSAVE 要 fork 子进程(复制内存页表):大实例(几 GB)fork 可能耗时(数百 ms~秒级)阻塞——所以持久化/备份注意大实例的 fork 影响(低峰执行、监控 fork 耗时)。
  • 扩展信息

    • 慢命令处理SLOWLOG(查看/配置)、KEYS *SCAN(游标遍历)、大集合用分页/HSCAN/SSCAN/ZSCAN(增量)
    • 持久化阻塞优化BGSAVE 后台、AOF everysec(别 always 拖写)、大实例错峰持久化、副本承载备份
    • 延迟排查工具redis-cli --latency(客户端视角延迟)、LATENCY DOCTOR(诊断)、监控(redis_exporter 延迟/命令耗时)

🤔 如何优化 Redis 的性能?

  • Redis 性能优化核心:①命令层(避免慢命令/大 key、用批量 Pipeline)②内存层(设 maxmemory、数据结构精简、防 swap)③持久化层(BGSAVE/异步、错峰)④网络层(连接池、客户端缓冲)⑤架构层(读写分离/Cluster 分片)。核心:“单线程下把慢命令/大 key/阻塞去掉,用批量与分片提吞吐”。

    • ① 命令层优化(最直接)
      • 避免慢命令KEYS *SCAN;大集合用分页(HSCAN/SSCAN/ZSCAN)
      • 避免大 key:拆大 key(大 List/Hash 拆分)、UNLINK 异步删
      • 批量Pipeline(批量发命令减少 RTT)、MGET/MSET
      • 合理过期:过期策略合理(防大量同过期雪崩,加随机)
    • ② 内存层优化
      • maxmemory + 淘汰策略(防内存无限涨/swap)
      • 数据结构精简:Hash 存对象(省内存)、用 listpack/紧凑结构
      • 防 swap(内存不足换页极慢)——内存要够
      • 碎片整理(activedefrag)、MEMORY USAGE 查大户
    • ③ 持久化层优化
      • BGSAVE(后台)别 SAVE(同步阻塞)
      • AOF everysec(别 always 拖写)
      • 大实例持久化错峰(低峰执行)、副本承载备份
    • ④ 网络/客户端优化
      • 连接池(客户端复用连接,别每请求新连)
      • client-output-buffer-limit(防慢客户端拖垮)
      • Pipeline/批量(减网络往返)
    • ⑤ 架构层优化
      • 读写分离(主写从读,分担读压力)
      • Cluster 分片(大数据量/写扩展)
      • 客户端就近(同机房,减延迟)
    • ⑥ 监控驱动
      • INFO(内存/命中率/命令耗时)、SLOWLOG(慢命令)、延迟监控
      • 发现瓶颈针对性优化(内存/慢命令/网络)
  • 协助记忆

    • 性能优化口诀:“命令(SCAN/批量/拆key)、内存(maxmemory/精简)、持久化(BGSAVE/错峰)、网络(连接池/批量)、架构(读写分离/分片)"。
    • 一句话:“单线程怕慢命令,先清命令再管内存/网络/架构”。
  • 进阶思考

    • Pipeline 和 MGET 有什么不同(怎么选)?
      • Pipeline:批量发多条命令(减少 RTT,命令可不同);MGET:一次取多 key(减少 RTT + 单命令)。Pipeline 更通用(任意命令),MGET 是"取多 key"专用(更简洁)。批量是减 RTT 的关键(网络往返是常见开销)。
    • “大 key"怎么影响性能(为什么优先处理)?
      • 大 key:①操作慢(遍历/传输大)②阻塞单线程(大 key 的 DEL/遍历卡住其他请求)③复制/迁移慢。优化优先:拆大 key(拆分/分片)——单线程下大 key 是"定时炸弹”。
    • 性能瓶颈怎么判断是内存/CPU/网络?
      • INFO stats(QPS)、INFO memory(内存)、used_cpu_*(CPU)、延迟(–latency);大并发场景常用网络(RTT)瓶颈、大数据场景内存瓶颈、复杂命令场景 CPU 瓶颈——按指标定位。
  • 扩展信息

    • 性能工具redis-benchmark(压测)、SLOWLOG(慢命令)、redis-cli --latency(延迟)、INFO(指标)、监控(redis_exporter)
    • 参数调优maxmemorymaxmemory-policyappendfsyncio-threads(6.0 网络多线程)、tcp-keepalive/连接超时
    • 设计优化:数据结构选型(省内存)、key 设计(避免无谓的膨胀)、业务层缓存策略(缓存击穿/雪崩防护)

🤔 Redis 6.0 多线程有了解过吗?多线程作用?

  • Redis 6.0 引入多线程(默认关闭,需配置开启):用多线程处理"网络 I/O”(socket 读/写、命令解析),但命令执行仍是单线程。作用:①提升网络吞吐(高并发大连接时瓶颈在网络 I/O,多线程并行处理读写)②命令执行逻辑不变(保持单线程简单/无锁)③解决"高并发下的网络 I/O 瓶颈”(不是解决 CPU 计算瓶颈)。

    • 为什么引入多线程(背景)
      • Redis 瓶颈常在"网络 I/O”(高并发时读/写 socket 消耗 CPU),而非命令执行(命令简单)
      • 单线程网络 I/O 在高并发连接下成瓶颈 → 6.0 用多线程并行处理网络 I/O
    • 多线程做什么(作用)
      • 网络 I/O 多线程:多条线程并行处理 socket 读/写、协议解析(accept/read/write)
      • 命令执行仍单线程:命令在单线程顺序执行(保持无锁/简单/有序)
      • 效果:网络吞吐提升(并发连接/大流量场景明显)
    • 配置
      • io-threads(线程数,如 4/8)、io-threads-do-reads(是否读也多线程,默认写多线程)
      • 注意:默认关闭(单线程);线程数建议 < CPU 核数;只影响网络 I/O 路径
    • 与"单线程快"的关系
      • 之前"单线程快"因内存快+多路复用;6.0 多线程补"网络 I/O 并行”(网络是外部 I/O,不影响命令逻辑)
      • 本质:“网络 I/O 并行 + 命令执行单线程”——兼顾吞吐与简单
    • 注意(多线程不是万能)
      • 只提升网络吞吐(大并发连接),不提升单命令性能(命令仍单线程串行)
      • CPU 计算密集场景(复杂命令)多线程帮助有限
      • 多线程有少量锁开销(网络层)——不是所有场景都更快
  • 协助记忆

    • 6.0 多线程 = “网络 I/O 并行(多线程读写 socket),命令执行还是单线程”。
    • 一句话:“多线程治网络吞吐瓶颈,命令逻辑保持单线程简单”。
  • 进阶思考

    • 为什么"命令执行"保持单线程(不一起多线程化)?
      • 命令单线程:①无锁(数据无需并发保护,简单可靠)②有序(命令顺序执行,语义明确)③Redis 命令简单(内存操作快,CPU 不是瓶颈)。网络 I/O 才是瓶颈 → 只多线程网络层(不破坏命令执行的优势)。
    • 多线程开启后会有副作用吗?
      • 有:网络层加锁开销(小)、线程上下文切换;线程数配置不当(太多)反而降性能。且只对"网络吞吐瓶颈"场景有效(大并发连接),普通场景收益有限甚至负。按需开启(压测确认)。
    • 6.0 多线程和"主从/集群复制"有关系吗?
      • 无直接关系:多线程是单节点内网络 I/O 优化;主从/集群是架构层(多节点)。两者独立(多线程优化单节点吞吐,集群扩展总吞吐)。
  • 扩展信息

    • Redis 版本演进(网络相关):1.x 单线程 → 6.0 网络 I/O 多线程(可选)→ 7.x 优化(如 I/O 线程改进)——演进方向"单线程命令 + 多线程 I/O"
    • 相关配置io-threads(网络 I/O 线程数)、io-threads-do-reads(读多线程)、tcp-backlog/连接数
    • 与 Memcached 对比:Memcached 多线程(处理 I/O + 命令);Redis 单线程命令 + 可选多线程 I/O——架构取舍不同

🤔 Redis 慢查询日志是什么?如何配置与使用?

  • Redis 慢查询日志(Slowlog)记录执行时间超过阈值的命令,用于排查慢命令/阻塞。配置:slowlog-log-slower-than(阈值,如 10000 微秒=10ms)、slowlog-max-len(保留条数);使用:SLOWLOG GET(查看)、SLOWLOG LEN(条数)、SLOWLOG RESET(清空)。

    • 是什么
      • Redis 记录"执行时间超过阈值"的命令(慢命令日志)
      • 用途:定位慢命令(单线程下慢命令阻塞其他请求,必须发现)
    • 配置参数
      • slowlog-log-slower-than:阈值(微秒),如 10000(10ms)以上记录;0 记录所有、负数关闭
      • slowlog-max-len:最多保留多少条(默认 128,环形覆盖)
      • 配置:CONFIG SET slowlog-log-slower-than 10000(运行时);持久化可 CONFIG REWRITE(7.0+ 写回 redis.conf)或改 redis.conf
    • 使用命令
      • SLOWLOG GET(查看,可 SLOWLOG GET 10 看最近 10 条)
      • SLOWLOG LEN(当前条数)
      • SLOWLOG RESET(清空)
    • 慢日志字段
      • 每条含:ID、时间戳、执行耗时(微秒)、命令及参数、客户端地址
      • duration(耗时)判断哪些命令慢
    • 怎么用(排查)
      • 定期 SLOWLOG GET 看慢命令(哪些命令/多少耗时)
      • 发现慢命令(如 KEYS *、大 key 操作)→ 优化(换 SCAN/拆 key)
      • 监控慢日志(告警:慢命令增多说明有问题)
  • 协助记忆

    • 慢查询日志 = “Redis 记’慢命令’的黑账”:超过阈值(slowlog-log-slower-than)就记录。
    • 口诀:“阈值 slowlog-log-slower-than、保留 slowlog-max-len、查看 SLOWLOG GET”。
  • 进阶思考

    • 慢查询阈值设多少合适?
      • 按业务延迟要求:高并发下 10ms 的单线程阻塞已明显拖慢业务,宜按延迟目标设 15ms(10005000 微秒);设太低会记太多(噪音)、太高漏掉影响。结合监控(延迟敏感度)调。
    • 慢日志能看到什么(怎么定位问题命令)?
      • duration(耗时)+ 命令(哪条慢)——找到"阻塞源命令"。结合上下文(哪时段/哪客户端)定位。慢命令通常是:KEYS *、大 key 的遍历/删除、SORT 大集合等。
    • 慢日志和"阻塞"什么关系?
      • 慢命令=执行慢(单线程下阻塞其他请求);慢日志就是"阻塞候选"的记录。持续有慢命令 → 会积累延迟/阻塞 → 必须处理(优化命令/拆 key)。慢日志是"提前发现阻塞源"的工具。
  • 扩展信息

    • 配置动态调整CONFIG SET slowlog-log-slower-than/slowlog-max-len(运行时生效,重启后失——要永久改 redis.conf)
    • 与其他诊断配合INFO commandstats(各命令累计耗时)、LATENCY DOCTOR(延迟诊断)、redis-cli --latency(客户端延迟)
    • 运维提示:慢日志也占内存(max-len 限制)、定期查看清理(SLOWLOG RESET

🤔 Redis 一般会监控哪些指标?

  • Redis 监控指标分几块:①可用性(ping/连接)②内存(used_memory/碎片/峰值/淘汰量)③性能(QPS/命令耗时/慢命令)④命中率(keyspace_hits/misses)⑤连接(connected_clients/被拒)⑥持久化(RDB/AOF 状态)⑦复制(主从状态/延迟)。核心:“内存、命中率、连接、复制、持久化"五块必盯,配 redis_exporter + Prometheus。

    • 可用性
      • ping(通不通)、进程/实例存活、uptime
    • 内存(最核心)
      • used_memory(使用内存)/ used_memory_peak(峰值)/ maxmemory(上限)
      • mem_fragmentation_ratio(碎片率,结合 used_memory 绝对量级判断:小实例数据量小时碎片率天然偏高,>1.5 不一定异常;大实例 >1.5 才需关注)
      • evicted_keys(淘汰 key 数,突然增多=内存压力)
      • 告警:内存使用率(70%/80%/90%)
    • 性能
      • QPS(total_commands_processed 速率)、命令耗时(INFO commandstats
      • SLOWLOG(慢命令数/时长)
      • 延迟(客户端视角 --latency
    • 命中率
      • keyspace_hits/keyspace_misses → 命中率(hits/(hits+misses)
      • 命中率低 = 缓存效率差(穿透/过期)
    • 连接
      • connected_clients(当前连接,接近 maxclients 告警)
      • rejected_connections(被拒连接,连接耗尽)
      • blocked_clients(阻塞连接,异常注意)
    • 持久化
      • rdb_last_bgsave_status(RDB 状态)、aof_enabled/aof_last_write_status(AOF)
      • 持久化失败告警(欠持久化=数据风险)
    • 复制(主从/集群)
      • role(主/从)、master_link_status(主从连接)
      • slave_repl_offset 差(复制延迟)、从库数
      • 集群:cluster_state、节点数
    • 实现
      • redis_exporter(Prometheus)采集 Redis 指标
      • Grafana 面板(Redis 官方/社区模板)
      • 告警:内存/命中率/连接/复制/持久化/慢命令
  • 协助记忆

    • 监控五块:“内存(used_memory/碎片)、命中率、连接、复制(offset 差)、持久化(aof/rdb)"。
    • 一句话:“redis_exporter 采指标,盯内存/命中/连接/复制/持久化五块”。
  • 进阶思考

    • 命中率低说明什么(怎么处理)?
      • 命中率低 = 大量请求没命中缓存(打 DB):可能缓存穿透/数据过期快/缓存没建好。处理:查穿透(布隆/空值)、调过期、确认缓存逻辑。命中率是"缓存有效性"的关键指标。
    • evicted_keys 突然增多意味着什么?
      • 淘汰 key 多 = 内存接近 maxmemory(触发淘汰):要么内存不够(扩容/清理),要么淘汰策略激进。持续淘汰会导致"缓存失效风暴”(大量 key 被淘汰→击穿 DB)——要关注。
    • 复制延迟怎么监控(多主从/集群)?
      • 主从:master_link_status(连接)+ offset 差(滞后量);集群:cluster_state + 各节点复制状态。复制断开/滞后告警(高可用风险)。
  • 扩展信息

    • 监控栈redis_exporter(指标采集)+ Prometheus(存储/告警)+ Grafana(看板)——标准组合
    • 关键告警示例:内存 >80%、命中率 <90%、连接接近 maxclients、主从断开、持久化失败、慢命令多
    • 云 Redis 监控:云厂商自带监控(内存/连接/命中率等),可配告警

🤔 Redis 如何提高安全性?

  • Redis 提高安全性:①认证(requirepass 密码/ACL 用户权限)②网络隔离(不暴露公网/防火墙/绑定内网)③禁用危险命令(rename-commandFLUSHALL/KEYS/CONFIG 等)④数据加密(TLS)⑤系统层(非 root 运行/最小权限)⑥防攻击(防暴力/未授权访问)。核心:“Redis 默认无认证,必须设密码 + 不暴露公网 + 禁危险命令”。

    • ① 认证(身份)
      • requirepass <password>:设置访问密码(所有连接需认证)
      • ACL(6.0+):更细粒度用户权限(每用户可访问 key/命令,ACL SETUSER
      • 生产必须设密码(Redis 默认无认证=裸奔)
    • ② 网络隔离(访问控制)
      • 不暴露公网:只在内网/防火墙内(bind 绑定内网 IP)
      • 防火墙限制来源(只允许应用服务器 IP)
      • 不监听公网端口(6379 不对外)
    • ③ 禁用危险命令(防滥用)
      • rename-command FLUSHALL ""(禁用)/KEYS/CONFIG/EVAL 等危险命令改名/禁用
      • 防:误操作(FLUSHALL 清库)、未授权滥用(CONFIG 改配置)
      • ACL 也可限制命令(6.0+)
    • ④ 数据加密(TLS)
      • tls-port(TLS 加密传输,6.0+ 支持)
      • 防窃听(明文协议 Redis 默认不加密)
    • ⑤ 系统/运行安全
      • 非 root 运行(专用用户)、最小权限(只读 Redis 目录)
      • 补丁(及时升级修复漏洞)、日志审计
    • ⑥ 其他
      • 防暴力破解(密码强度 + 防火墙/fail2ban 限源;Redis 无内置登录失败锁定,可用 6.0+ ACL LOG 监控未授权尝试)
      • 监控未授权访问尝试(日志/告警)
      • 内网也是威胁面(内网也有攻击者)——安全是常态不是可选项
  • 协助记忆

    • 安全口诀:“设密码(requirepass/ACL)、不暴露(内网绑定)、禁危险命令(rename)、非 root 运行、TLS 加密”。
    • 一句话:“Redis 默认裸奔,设密+隔离+禁危险命令是底线”。
  • 进阶思考

    • 为什么 Redis 默认"无认证”(很危险)?
      • Redis 设计为"内网可信环境"(高性能、协议简单,默认不强制认证)——但如果暴露公网/内网失陷,无认证=可任意读写(清库/窃数据)。所以生产必须显式设密码 + 隔离。
    • ACL(6.0+)比 requirepass 强在哪?
      • requirepass:一个全局密码(所有连接同一权限);ACL:多用户 + 细粒度权限(每用户限制可访问的 key/命令)——更精细(如只读用户/指定 key 范围)。安全要求高用 ACL。
    • “危险命令"为什么必须禁(具体危害)?
      • FLUSHALL(清空所有数据)、CONFIG SET(改配置,如关密码/改持久化)、KEYS *(阻塞)、EVAL(Lua 可执行代码)——被未授权/攻击者利用危害大。rename-command 禁用/改名可防。
  • 扩展信息

    • ACL 命令ACL SETUSER/ACL GETUSER/ACL LIST(用户管理)、ACL CAT(命令类别)
    • 配置安全bind(绑定 IP)、protected-mode(保护模式,默认 yes 未认证时限本机)、rename-command
    • 审计/合规:安全日志(连接/命令审计)、等保对 Redis 等中间件安全要求(认证/访问控制/加密)

目录