Files
interview/questions/03-缓存/Redis数据结构.md
yasinshaw 0e46a367c4 refactor: rename files to Chinese and organize by category
Organized 50 interview questions into 12 categories:
- 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc.
- 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理
- 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc.
- 04-消息队列 (1 file): RocketMQ/Kafka
- 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc.
- 06-JVM (1 file): JVM和垃圾回收
- 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc.
- 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮
- 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化
- 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx
- 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性
- 12-面试技巧 (1 file): 面试技巧和职业规划

All files renamed to Chinese for better accessibility and
organized into categorized folders for easier navigation.

Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-01 00:10:53 +08:00

216 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Redis 数据结构
## 问题
1. Redis 有哪些数据结构?底层实现是什么?
2. String 类型的应用场景?
3. Hash 和 String 的区别?
4. List 的应用场景?
5. Set 和 ZSet 的区别?
6. Bitmap、HyperLogLog、GEO 的应用?
---
## 标准答案
### 1. Redis 数据类型
| 类型 | 底层实现 | 应用场景 |
|------|---------|----------|
| **String** | SDS | 缓存、计数器、分布式锁 |
| **Hash** | 压缩列表/哈希表 | 对象存储、购物车 |
| **List** | 双向链表/压缩列表 | 消息队列、最新列表 |
| **Set** | 哈希表/整数集合 | 标签、共同关注 |
| **ZSet** | 跳表/哈希表 | 排行榜、延时队列 |
| **Bitmap** | String位操作 | 签到、在线用户 |
| **HyperLogLog** | String基数统计 | UV 统计 |
| **GEO** | ZSet经纬度编码 | 附近的人 |
---
### 2. StringSDS - Simple Dynamic String
**结构**
```c
struct sdshdr {
int len; // 已使用长度
int free; // 剩余空间
char buf[]; // 字节数组
};
```
**优势**
- O(1) 获取长度
- 防止缓冲区溢出
- 减少内存分配次数
**应用**
```bash
# 缓存
SET user:1001 '{"id":1001,"name":"Alice"}'
GET user:1001
# 计数器
INCR view_count:1001
DECR stock:1001
# 分布式锁
SET lock:order:1001 "uuid" NX PX 30000
```
---
### 3. Hash
**结构**
```bash
HSET user:1001 name "Alice" age 25 email "alice@example.com"
HGET user:1001 name
HGETALL user:1001
```
**底层**
- 字段少(< 512压缩列表ziplist
- 字段多(≥ 512哈希表hashtable
**应用**
```java
// 对象存储(推荐 Hash而非 String
redisTemplate.opsForHash().putAll("user:1001", Map.of(
"name", "Alice",
"age", "25"
));
// 购物车
redisTemplate.opsForHash().put("cart:1001", "product:1001", "2");
```
---
### 4. List
**结构**
```bash
LPUSH list:msgs "msg1" "msg2" "msg3" # 左侧插入
RPOP list:msgs # 右侧弹出
```
**底层**
- 元素少(< 512压缩列表ziplist
- 元素多(≥ 512双向链表linkedlist
- Redis 3.2+quicklistziplist + linkedlist
**应用**
```bash
# 消息队列
LPUSH queue:email '{"to":"alice@example.com","subject":"Hello"}'
RPOP queue:email
# 最新列表
LPUSH timeline:1001 "post1" "post2"
LRANGE timeline:1001 0 9 # 最新 10 条
```
---
### 5. Set vs ZSet
**Set无序集合**
```bash
SADD tags:article:1001 "java" "redis" "mysql"
SMEMBERS tags:article:1001
SISMEMBER tags:article:1001 "java"
SINTER tags:user:1001 tags:article:1001 # 交集
```
**底层**
- 元素少(< 512整数集合intset
- 元素多(≥ 512哈希表hashtable
---
**ZSet有序集合**
```bash
ZADD rank:score 100 "player1" 200 "player2" 150 "player3"
ZREVRANGE rank:score 0 9 WITHSCORES # Top 10
ZRANK rank:score "player1" # 排名
ZSCORE rank:score "player1" # 分数
```
**底层**
- 元素少(< 128压缩列表ziplist
- 元素多(≥ 128跳表skiplist + 哈希表hashtable
---
### 6. Bitmap
**原理**:用 bit 位表示状态0 或 1
```bash
# 签到
SETBIT sign:2024:02:28:1001 0 1 # 用户 1001 在第 0 天签到
SETBIT sign:2024:02:28:1001 4 1 # 用户 1001 在第 4 天签到
# 统计签到天数
BITCOUNT sign:2024:02:28:1001
# 用户 1001 和 1002 共同签到的天数
BITOP AND result sign:2024:02:28:1001 sign:2024:02:28:1002
BITCOUNT result
```
---
### 7. HyperLogLog
**用途**:基数统计(不重复元素个数)
**优点**内存占用极小12 KB
```bash
PFADD uv:2024:02:28 user:1001 user:1002 user:1003
PFCOUNT uv:2024:02:28 # 3
# 合并多个 HyperLogLog
PFMERGE uv:2024:02:01-28 uv:2024:02:01 uv:2024:02:02 ...
```
**误差率**< 1%
---
### 8. GEO地理位置
```bash
# 添加位置
GEOADD locations:users 116.404 39.915 "user:1001" # 北京
# 查找附近的人5 km 内)
GEORADIUS locations:users 116.404 39.915 5 km
# 计算距离
GEODIST locations:users user:1001 user:1002
```
**底层**ZSet经纬度编码为 score
---
### 9. 阿里 P7 加分项
**深度理解**
- 理解 SDS 和 C 字符串的区别
- 理解跳表的实现原理
- 理解压缩列表的优缺点
**实战经验**
- 有选择合适数据类型的经验
- 有大数据量下的优化经验
- 有 Redis 内存优化的经验
**架构能力**
- 能设计基于 Redis 的业务方案
- 能设计 Redis 集群方案
- 能设计 Redis 监控体系