Redis 五大数据结构及使用场景
一句话
Redis 提供 5 种基本数据结构(String、Hash、List、Set、ZSet),外加 3 种高级结构(Bitmap、HyperLogLog、Geo),每种都针对特定场景优化。面试重点是知道什么场景用什么结构。
1. String(字符串)
最基本的数据类型,最大 512MB,可以是文本也可以是二进制。
常用命令:SET / GET / MSET / MGET / INCR / DECR 底层数据结构:SDS(Simple Dynamic String),支持动态扩容,二进制安全| 场景 | 示例 |
|---|---|
| 普通缓存 | SET user:1001 '{"name":"Alice","age":30}' |
| 计数器 | INCR article:read:123(原子自增) |
| 分布式锁 | SET lock_key true NX EX 10(NX=不存在才设置,EX=10 秒过期) |
| Session | SET session:abc123 '{"userId":1001}' EX 1800 |
2. Hash(哈希)
一个 key 对应多个 field-value,适合存储对象。
常用命令:HSET / HGET / HMSET / HMGET / HDEL / HINCRBY 底层数据结构:ziplist(小数据量) → hashtable(大数据量)| 场景 | 示例 |
|---|---|
| 对象缓存 | HSET user:1001 name Alice age 30 |
| 购物车 | HSET cart:1001 sku_123 2(field=商品 ID, value=数量) |
String 存对象 vs Hash 存对象
String 方式: SET user:1001 '{"name":"Alice","age":30}' → 改一个字段要序列化整个对象再写回去 Hash 方式: HSET user:1001 name Alice HSET user:1001 age 30 → 改一个字段只需要 HSET 单个字段,更灵活更省内存3. List(列表)
有序的字符串链表,两端插入弹出都是 O(1)。
常用命令:LPUSH / RPUSH / LPOP / RPOP / LRANGE / BLPOP 底层数据结构:quicklist(ziplist + 双向链表)| 场景 | 示例 |
|---|---|
| 消息队列 | LPUSH queue:task task_001,BRPOP queue:task 30(阻塞消费) |
| 最新列表 | LPUSH news:latest news_id+LTRIM news:latest 0 9(只保留最新 10 条) |
| 栈/队列 | LPUSH+RPOP=队列,LPUSH+LPOP=栈 |
4. Set(集合)
无序不重复的字符串集合,支持集合运算。
常用命令:SADD / SREM / SMEMBERS / SISMEMBER / SINTER / SUNION / SDIFF 底层数据结构:intset(全是整数且数量少) → hashtable| 场景 | 示例 |
|---|---|
| 点赞/标签 | SADD news:123:liked user_456,SISMEMBER news:123:liked user_456 |
| 共同关注 | SINTER follow:A follow:B(A 和 B 的共同关注) |
| 好友推荐 | SDIFF follow:A follow:B(A 关注但 B 没关注的人) |
| 去重 | SADD unique:ids id1 id2 id3(自动去重) |
5. ZSet(有序集合)
每个 member 关联一个 score,按 score 自动排序。
常用命令:ZADD / ZREM / ZSCORE / ZRANGE / ZREVRANGE / ZINCRBY 底层数据结构:ziplist(少量数据) → skiplist + hashtable(跳表 + 哈希表)| 场景 | 示例 |
|---|---|
| 排行榜 | ZINCRBY rank:2024 player_789 10,ZREVRANGE rank:2024 0 9 WITHSCORES |
| 延迟队列 | score=执行时间戳,定时扫描 score <= now 的任务 |
| 滑动窗口限流 | score=时间戳,ZREMRANGEBYSCORE 清理过期记录 |
6. 三种高级结构(了解即可)
| 结构 | 原理 | 场景 |
|---|---|---|
| Bitmap | 操作字符串的每一位,极其省空间 | 用户签到(SETBIT sign:1001 100 1) |
| HyperLogLog | 概率数据结构,估算不重复元素数,误差 0.81%,只占 12KB | UV 统计 |
| Geo | 基于 ZSet 实现,存储经纬度 | 附近的人(GEORADIUS cities 116.40 39.90 100 km) |
7. 底层数据结构总结
面试可能追问底层实现:
String → SDS(动态字符串,预分配内存,减少 realloc) Hash → ziplist(元素少且小) → hashtable(元素多) List → quicklist(ziplist + 双向链表的折中方案) Set → intset(全是整数且 ≤ 512 个) → hashtable ZSet → ziplist(元素少) → skiplist + hashtable核心思路:数据少时用压缩结构省内存,数据多时切换到高效结构。
🎙 面试回答模板
"Redis 有 5 种基本数据结构。String 最通用,能做缓存、计数器、分布式锁; Hash 适合存对象,比如用户信息或购物车,可以单独更新某个字段, 比 String 存整个 JSON 更灵活;List 是有序列表,可以当消息队列或最新消息列表; Set 是无序不重复集合,支持交集并集差集,适合做点赞、标签、共同关注; ZSet 是带分数的有序集合,最经典的场景就是排行榜。 另外还有 Bitmap 做签到、HyperLogLog 做 UV 统计、Geo 做附近的人, 这三种了解场景就行。 底层实现方面,Redis 会根据数据量自动选择压缩结构或高效结构, 数据少时用 ziplist/intset 省内存,数据多时切换到 hashtable/skiplist。"参考来源
01_Raw【原始素材】/notion 资料/Notion/任务/Redis核心数据结构实战+服务搭建.md01_Raw【原始素材】/notion 资料/Notion/任务/Redis7 底层数据结构解析.md- Redis 官方文档:Data types
