# 运维常见题-Redis维护


## 🤔 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-lru` 或 `volatile-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 秒/不丢）②可读/可修复（文本命令）
        - 缺点：①文件大（所有命令累积）②恢复慢（重放所有命令）③写性能影响（要刷盘）
    - **对比**
        | 维度 | RDB | AOF |
        |------|-----|-----|
        | 存储 | 快照（数据） | 命令日志 |
        | 体积 | 小 | 大（可重写） |
        | 恢复 | 快 | 慢 |
        | 丢数据 | 可能（间隔间） | 少（按策略） |
        | 写性能 | 好 | 略差（刷盘） |
    - **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 rewrite`（`BGREWRITEAOF`）：重写成"当前数据的最新命令"（瘦身）——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 memory`：`used_memory`（实际使用）、`used_memory_human`、`used_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）
        - 慢命令/连接数（连接也占内存）
    - **第四步：解决**
        - **删大 key**：`UNLINK`（异步删除，不阻塞）、拆分大 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 memory`、`MEMORY USAGE key`、`MEMORY DOCTOR`、`MEMORY PURGE`、`redis-cli --bigkeys`、`CONFIG 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_human`、`used_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_enabled`、`aof_last_write_status`、`aof_rewrite_in_progress`
        - **`replication`（主从）**：`role`（master/slave）、`connected_slaves`（从库数）、`master_link_status`（主从连接）、`slave_repl_offset`（复制偏移）
        - **`cpu`**：`used_cpu_sys`/`used_cpu_user`（CPU 使用）
        - **`server`**：`redis_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 replication` 的 `connected_slaves`/`slave_repl_offset` 字段当前版本仍用 slave 命名（官方术语迁移尚未完成）

## 🤔 Redis 主从复制延迟过高怎么解决？  
- **Redis 主从复制延迟（从库数据滞后于主库）原因：①网络延迟/带宽（主从传输慢）②从库处理慢（大命令/从库负载高）③主库写入量大（同步跟不上）④积压缓冲区太小（触发全量）。解决：网络优化、减从库负载、`repl-backlog-size` 调大、主库写入分担、监控延迟。**  
    - **常见原因**
        - **网络**：主从跨机房/带宽不足（传输慢）
        - **从库负载高**：从库跑重查询/慢命令（处理命令慢）
        - **主库写入量大**：写命令多，同步跟不上
        - **大命令/大 key**：单条命令复制慢（大 key 传输）
        - **积压缓冲区小**：断线后无法增量（触发全量复制，更慢）
        - **同步复制写阻塞**：配了 `WAIT` 等从库确认——增加的是主库**写响应延迟**（与“从库滞后”机理不同，属写延迟口径）
    - **查看延迟**
        - `INFO replication`：看 `master_repl_offset` 和 `slave_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. 哨兵监控主库（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`）
    - **示例（概念）**
        ```java
        // 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. 写 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 INFO` 的 `cluster_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 stats`（`latest_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）
    - **参数调优**：`maxmemory`、`maxmemory-policy`、`appendfsync`、`io-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 的单线程阻塞已明显拖慢业务，宜按延迟目标设 1~5ms（1000~5000 微秒）；设太低会记太多（噪音）、太高漏掉影响。结合监控（延迟敏感度）调。
    - **慢日志能看到什么（怎么定位问题命令）？**
        - 看 `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-command`：`FLUSHALL`/`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 等中间件安全要求（认证/访问控制/加密）




---

> 作者: [0x5c0f](https://blog.0x5c0f.cc)  
> URL: https://blog.0x5c0f.cc/posts/other/%E8%BF%90%E7%BB%B4%E5%B8%B8%E8%A7%81%E9%A2%98-redis%E7%BB%B4%E6%8A%A4/  

