60 秒回答模板

Redis 常见 value 类型有 String、Hash、List、Set、ZSet,也有 Bitmap、HyperLogLog、Geo、Stream 等结构。回答时按场景选型:String 做缓存、计数和分布式锁值;Hash 存对象字段;List 做简单队列;Set 做去重和集合运算;ZSet 做排行榜和延迟队列;Stream 更适合消费组消息流。再补充底层编码会随元素数量和大小变化,例如 SDS、listpack、intset、hashtable、skiplist,并说明命令复杂度和 big key 风险。

考点 核心机制与工程取舍
难度 中高频面试题
回答目标 按定义、机制、场景讲清楚

深入解析

01

先按业务访问模式选类型

点查缓存和计数用 String,字段级对象更新用 Hash,去重和交并差用 Set,按分数排序或范围分页用 ZSet,可靠消费组消息更适合 Stream。

02

基础类型要配典型命令

`GET/SET/INCR` 对应 String,`HGET/HSET` 对应 Hash,`LPUSH/BRPOP` 对应 List,`SADD/SISMEMBER` 对应 Set,`ZADD/ZRANGE/ZREVRANK` 对应 ZSet。面试时要能说出常用命令的大致复杂度。

03

底层编码不是固定一种结构

String 基于 SDS;小 Hash、List、ZSet 可能用 listpack;小整数 Set 可能用 intset;规模变大后会转 hashtable 或 skiplist 加 dict。编码转换会影响内存和性能。

04

扩展结构解决特定问题

Bitmap 适合签到和布尔状态集合;HyperLogLog 估算 UV 但有误差;Geo 适合经纬度半径查询;Stream 提供消息 ID、消费组、pending 列表,比 List 更适合可追踪消费。

05

工程上要防 big key 和慢命令

超大 Hash、Set、ZSet 会阻塞主线程、拖慢删除和迁移。范围扫描优先用渐进式命令,删除大 key 用异步删除或拆分 key,避免线上直接 `KEYS` 扫全库。

易错点

  • 只列 String、Hash、List、Set、ZSet,不说明业务场景。
  • 把 Redis 类型和 Java 集合一一等同,忽略编码转换。
  • 不提命令复杂度,随意对大集合做范围或全量操作。
  • 把 List 当可靠消息队列,不考虑 ack、重试和消费组语义。

面试官追问

排行榜为什么常用 ZSet?

ZSet 同时维护 member 和 score,能按分数排序、查排名、取区间和更新分数,天然适合排行榜。

Hash 一定比 String 存 JSON 更好吗?

不一定。Hash 支持字段级更新,小对象可能更省内存;但字段太多会变成 big key,JSON 读写简单但更新要整体替换。

List 和 Stream 做消息有什么区别?

List 更像简单阻塞队列,缺少消费组、ack 和 pending 管理;Stream 更适合多消费者组和可追踪重试。

HyperLogLog 能拿来精确去重吗?

不能。它用于基数估算,内存小但有误差;精确去重要用 Set、Bitmap 或外部存储。