# 1. Redis 的五大基础数据结构,String、Hash、List、Set、ZSet 的底层实现? A 所有数据结构底层都固定使用哈希表实现 B List 底层只能是双端链表 C 每种结构会根据数据规模和数据特点动态切换底层编码 ✓ 正确答案 D ZSet 底层只能是跳表
# 2. Redis 对象编码(OBJ_ENCODING 取值 int/embstr/raw/listpack/hashtable/skiplist/quicklist)如何随数据规模动态切换以节省内存?如何用 OBJECT ENCODING/OBJECT HELP 观察? A 编码切换通常由数据规模或元素长度阈值触发 ✓ 正确答案 B embstr 编码用于存储任意长度的字符串 C int 编码用于存储所有类型的 value D encoding 切换后一定会自动降级
# 3. ziplist 连锁更新(cascade update,前一节点长度跨越 254 字节阈值导致 prevlen 字段 1→5 字节、引发后续节点连锁扩容)的原理是什么?listpack 如何通过记录条目总长、支持反向遍历从根本上规避? A 连锁更新是 listpack 中 prevlen 字段引起的 B 连锁更新无法避免 C 连锁更新最坏情况是 O(N) 复杂度 D listpack 通过记录每个条目的自身长度来规避连锁更新 ✓ 正确答案
# 4. Redis 7 为何用 listpack 全面替代 ziplist 作为小对象编码?二者在内存布局与遍历安全性上有何差异? A listpack 消除了 ziplist 的连锁更新问题 ✓ 正确答案 B ziplist 比 listpack 更节省内存 C Redis 7 仍默认使用 ziplist 作为小对象编码 D listpack 不支持反向遍历
# 5. Redis Streams 的概念与命令,XADD、XREAD、XREADGROUP? A Streams 消息不可持久化 B Streams 不支持多消费者组 C XADD 用于读取消息 D XREADGROUP 用于消费组读取并支持 ACK 确认 ✓ 正确答案
# 6. Hash 在数据量小/大时的底层切换,listpack(ziplist)→ hashtable? A 切换由元素数量和单个元素长度阈值触发 ✓ 正确答案 B 数据量大时 Hash 使用 listpack 编码 C 切换后编码会随数据变小自动降级 D hashtable 比 listpack 更省内存
# 7. List 的 quicklist(双向链表 + listpack)实现? A quicklist 是纯哈希表 B quicklist 无法支持 O(1) 头尾插入 C quicklist 是双向链表,每个节点内部是 listpack ✓ 正确答案 D quicklist 每个条目单独分配一个节点
# 8. String 的 SDS(Simple Dynamic String)实现与 C 字符串的对比? A C 字符串获取长度是 O(1) B SDS 不能存储二进制数据 C SDS 追加时不做空间预分配 D SDS 是二进制安全的 ✓ 正确答案
# 9. ZSet 的跳表(Skip List)+ 哈希表实现? A ZSet 只用跳表实现 B 跳表用于按分数排序与范围查询 ✓ 正确答案 C 哈希表用于按分数范围查询 D ZSet 用红黑树实现排序
# 10. Set 的 intset + hashtable 实现? A Set 永远使用 intset 编码 B intset 中元素无序存储 C hashtable 中 Set 元素作为 value D 元素为整数且数量较少时用 intset,否则用 hashtable ✓ 正确答案
# 11. Streams 的 PEL(Pending Entries List)? A PEL 记录已确认的消息 B XACK 会向 PEL 添加消息 C PEL 记录已读取但未 ACK 的消息,用于消息重投与故障恢复 ✓ 正确答案 D PEL 只存在于 Redis 内存不持久化
# 12. 消费组(Consumer Group)的实现与消息确认? A XACK 用于确认消息,确认后从 PEL 移除 ✓ 正确答案 B 消息确认后仍留在 PEL 中 C 一个消费组只能有一个消费者 D 消费组不支持消息重投
# 13. Valkey 8.0 (BSD-3-Clause fork 后的首个 major release):与 Redis 7 / Redis 8 OSS 的协议兼容性、命令集、性能对比? A Valkey 使用与 Redis 不兼容的私有协议 B Valkey 是 Redis 协议兼容的 BSD-3-Clause 分支 ✓ 正确答案 C Valkey 不支持 Lua 脚本 D Valkey 与 Redis 命令集完全不同
# 14. Redis 8 OSS 内置 time series / JSON / search / vector 数据结构:与传统 Redis 用 Stack (RediSearch + RedisJSON + RedisTimeSeries) 模块的差异? A Redis 8 内置结构仍需手动加载模块 B Redis 8 不支持 JSON 数据结构 C 内置结构开箱即用,模块化方式更灵活 ✓ 正确答案 D 模块方式比内置方式更稳定
# 15. Redis 的 Bitmap、HyperLogLog、GEO 三种扩展数据结构(SETBIT/BITCOUNT、PFADD/PFCOUNT、GEOADD/GEOSEARCH)的底层实现与典型场景? A HyperLogLog 能精确统计基数 B Bitmap 底层是 String 的位数组 ✓ 正确答案 C GEO 直接以字符串存储经纬度 D HyperLogLog 内存随数据量线性增长
# 16. Redis 7.x 的 listpack 与 quicklist 演进,大 key 的识别与治理手段? A 大 Key 不会影响主线程 B UNLINK 会同步阻塞删除大 Key C 大 Key 只能删除无法治理 D --bigkeys 用 SCAN 采样识别大 Key ✓ 正确答案
# 17. Redis 大 Key 与热 Key 的识别(--bigkeys、SCAN 采样、monitor)与治理(拆分、压缩、多级缓存)? A 热 Key 只能通过扩容解决 B 大 Key 对性能没有影响 C --hotkeys 依赖 LFU 命中统计识别热 Key ✓ 正确答案 D MONITOR 用于识别大 Key
# 18. Redis 内存碎片率(mem_fragmentation_ratio)的成因与治理(activedefrag、合理 maxmemory)? A 碎片率越高说明内存越紧凑 B 碎片率与内存分配器无关 C activedefrag 可后台整理内存碎片 ✓ 正确答案 D 碎片率只能通过重启解决
# 19. Redis 对象共享(整数共享、命令结果缓存)与内存优化的工程实践? A 对象共享无法节省内存 B 整数共享池覆盖所有整数 C 命令结果缓存会降低性能 D Redis 对 0-9999 的整数复用共享对象 ✓ 正确答案
# 20. Streams 与消息队列(Kafka、RocketMQ)的取舍? A Streams 更适合轻量低延迟的简单消息场景 ✓ 正确答案 B Streams 适合高吞吐海量消息 C Kafka 不适合分区并行 D RocketMQ 不支持事务消息
# 21. Valkey 8 的多线程模型变化对 Redis cluster topology 设计的兼容性影响? A Valkey 8 修改了 Cluster 协议 B 多线程会改变槽位分配规则 C Valkey 8 不支持 RESP3 D 多线程仅用于 IO 读写,命令执行仍串行,拓扑兼容 ✓ 正确答案
# 22. Redis License 变更(RSALv2/SSPLv1 双许可,Redis 8 起增加 AGPLv3 三许可选项)后的合规考量:企业选择 Redis 8 OSS、Valkey 8、还是 Redis Enterprise 的判断框架? A Valkey 采用 RSALv2 许可 B Redis 8 OSS 提供 BSD-3-Clause 许可 C 企业选型需考虑是否对外提供 Redis 托管服务及许可宽松度 ✓ 正确答案 D Redis Enterprise 是免费开源的
# 23. ZSet 的跳表+哈希实现,为什么跳表而不是红黑树,跨度字段作用? A 红黑树实现比跳表简单 B 跳表查找复杂度是 O(N) C 跳表配合跨度字段便于排名与范围查询 ✓ 正确答案 D 跨度字段用于存储成员分数
# 24. Redis 8 的 RESP3 与客户端缓存(Client-Side Caching)如何减少网络往返与延迟? A RESP3 只支持字符串类型 B RESP3 不支持 push 消息 C 客户端缓存无法保证一致性 D 客户端缓存通过服务端失效通知减少网络往返 ✓ 正确答案
# 25. Redis 的 SDS 与整数集合,内存优化与小对象编码转换? A SDS 不做空间预分配 B intset 支持任意类型元素 C 小对象编码转换只由元素数量决定 D intset 用有序数组紧凑存储小整数集合 ✓ 正确答案