第三章 基础数据结构 v1.0
一、Redis 数据结构概览
Redis 提供了多种数据结构,每种都有不同的适用场景。选择合适的数据结构可以让开发更高效、性能更优。
| 数据结构 | 说明 | 典型场景 |
|---|---|---|
| String | 字符串,最基础的类型 | 缓存、计数器、分布式锁 |
| Hash | 哈希表,存储对象 | 用户信息、商品详情 |
| List | 有序列表 | 消息队列、最新动态 |
| Set | 无序集合,元素唯一 | 标签、好友关系、去重 |
| Sorted Set | 有序集合,按分数排序 | 排行榜、延迟队列 |
二、String(字符串)
String 是 Redis 最基本的类型,一个 key 对应一个 value。字符串 value 最大可以存储 512MB。
String 是二进制安全的,可以包含任意数据(图片、序列化对象等)。
1.内部编码
| 编码方式 | 条件 |
|---|---|
| int | 值为整数且小于 2^63 |
| embstr | 值为字符串且长度 ≤ 44 字节 |
| raw | 值为字符串且长度 > 44 字节 |
2.典型场景
bash
# 缓存
SET user:1001 '{"name":"John","age":25}'
# 计数器
INCR article:1001:views
# 分布式锁
SET lock:order:1001 "owner_id" EX 10 NX
# Session 存储
SET session:abc123 "user_data" EX 3600三、Hash(哈希)
Hash 是 field 和 value 的映射表,适合存储对象。每个 Hash 可以存储 2^32 - 1 个键值对(40多亿)。
1.内部编码
| 编码方式 | 条件 |
|---|---|
| ziplist | 字段数量 < 128 且每个值 < 64 字节 |
| hashtable | 不满足 ziplist 条件时自动转换 |
2.典型场景
bash
# 存储用户信息
HSET user:1001 name "John" age 25 city "Beijing"
# 购物车
HSET cart:user1001 product:2001 1
HSET cart:user1001 product:2002 33.与 String 存储对象的对比
| 对比项 | String (JSON) | Hash |
|---|---|---|
| 读取单个字段 | 需要反序列化整个 JSON | 直接读取 |
| 更新单个字段 | 需要读取→修改→写入 | 直接修改 |
| 内存占用 | 较少 | ziplist 较少,hashtable 较多 |
| 适用场景 | 读多写少、整体操作 | 需要频繁读写单个字段 |
四、List(列表)
List 是按照插入顺序排序的字符串列表,可以从头部或尾部操作。一个列表最多可以存储 2^32 - 1 个元素。
1.内部编码
| 编码方式 | 条件 |
|---|---|
| ziplist | 元素数量 < 128 且每个值 < 64 字节 |
| linkedlist | 不满足 ziplist 条件时自动转换 |
2.典型场景
bash
# 消息队列(简易版)
LPUSH msg:queue "message1"
RPOP msg:queue
# 最新动态列表
LPUSH timeline:user1001 "post:5001"
LTRIM timeline:user1001 0 49 # 只保留最新50条
# 阻塞队列
BRPOP msg:queue 30 # 阻塞等待,最多30秒五、Set(集合)
Set 是 String 类型的无序集合,成员唯一。通过哈希表实现,添加、删除、查找的复杂度都是 O(1)。
1.内部编码
| 编码方式 | 条件 |
|---|---|
| intset | 全部为整数且数量 < 128 |
| hashtable | 不满足 intset 条件时 |
2.典型场景
bash
# 标签系统
SADD article:1001:tags "redis" "database" "nosql"
# 好友关系
SADD user:1001:friends 1002
SADD user:1001:friends 1003
# 共同好友
SINTER user:1001:friends user:1002:friends
# 去重统计
SADD ip:2024-01-01 "192.168.1.1"
SCARD ip:2024-01-01 # 统计独立 IP 数六、Sorted Set(有序集合)
Sorted Set 的每个成员关联一个 double 类型的分数(score),Redis 根据分数从小到大排序。成员唯一,分数可以重复。
1.内部编码
| 编码方式 | 条件 |
|---|---|
| ziplist | 元素数量 < 128 且每个值 < 64 字节 |
| skiplist | 不满足 ziplist 条件时自动转换 |
2.典型场景
bash
# 排行榜
ZADD leaderboard 95 "player:1001"
ZADD leaderboard 87 "player:1002"
ZADD leaderboard 99 "player:1003"
# 获取 Top 3(分数从高到低)
ZREVRANGE leaderboard 0 2 WITHSCORES
# 延迟队列(分数 = 执行时间戳)
ZADD delay:queue 1704067200 "task:1"
# 范围查询
ZRANGEBYSCORE delay:queue 0 1704067200 LIMIT 0 10七、数据结构选择建议
| 需求 | 推荐结构 | 原因 |
|---|---|---|
| 简单缓存 | String | 最简单高效 |
| 存储对象(需独立修改字段) | Hash | 支持单字段操作 |
| 排序、排名 | Sorted Set | 天然支持分数排序 |
| 去重、交集、并集 | Set | 唯一性 + 集合运算 |
| 先进先出队列 | List | 头尾操作 O(1) |
| 消息队列(需要确认) | Stream | 持久化 + 消费者组 |
| 统计 UV | HyperLogLog | 固定内存,大数据量 |
| 签到打卡 | BitMap | 按 bit 存储,极省内存 |
| 地理位置 | Geo | 内置距离计算 |