Redis 数据结构详解
1. 字符串(String)
特点
- 最基本的数据类型,可存储 文本、二进制数据(如图片)或 数值。
- 最大容量:512MB。
底层实现
- 动态字符串(SDS, Simple Dynamic String):
- 预分配冗余空间(减少内存频繁分配)。
- 二进制安全(可存储任意数据,包括
\0
)。
常用命令
SET key value # 设置值
GET key # 获取值
INCR key # 数值+1
APPEND key "new" # 追加字符串
STRLEN key # 获取长度
应用场景
- 缓存用户会话(Session)、计数器(如文章阅读量)、分布式锁。
2. 列表(List)
特点
- 有序的元素集合,支持双向操作(头尾插入/删除)。
- 元素可重复。
底层实现
- 快速列表(QuickList,Redis 3.2+):
- 由多个 压缩列表(ZipList) 节点组成的双向链表。
- 平衡内存效率和操作速度。
常用命令
LPUSH key value1 # 头部插入
RPOP key # 尾部删除
LRANGE key 0 -1 # 获取所有元素
LINDEX key 0 # 获取第一个元素
LLEN key # 获取长度
应用场景
- 消息队列(生产者-消费者模型)、最新消息排行(如微博时间线)。
3. 哈希(Hash)
特点
- 键值对集合,适合存储 对象(如用户信息)。
- 可单独操作字段,无需读取整个哈希。
底层实现
- ZipList(元素少时) 或 HashTable(元素多时):
- 默认使用
ZipList
(内存紧凑),当元素数量或大小超过阈值时转为HashTable
。
- 默认使用
常用命令
HSET user:1 name "John" # 设置字段
HGET user:1 name # 获取字段
HGETALL user:1 # 获取所有字段
HDEL user:1 age # 删除字段
应用场景
- 存储对象(用户信息、商品详情)、聚合统计(如用户标签)。
4. 集合(Set)
特点
- 无序、唯一的元素集合。
- 支持交集、并集、差集运算。
底层实现
- IntSet(整数集合) 或 HashTable:
- 元素全为整数且数量较少时使用
IntSet
,否则转为HashTable
。
- 元素全为整数且数量较少时使用
常用命令
SADD tags "Java" # 添加元素
SREM tags "Python" # 删除元素
SMEMBERS tags # 获取所有元素
SINTER set1 set2 # 求交集
SCARD tags # 获取元素数量
应用场景
- 标签系统(如文章标签)、共同好友(社交关系)、去重(UV统计)。
5. 有序集合(Sorted Set / ZSet)
特点
- 元素 唯一,每个元素关联一个 分数(Score),按分数排序。
- 支持范围查询和排名操作。
底层实现
- 跳跃表(SkipList) + HashTable:
HashTable
存储元素到分数的映射。SkipList
按分数排序,支持快速范围查询。
常用命令
ZADD rank 90 "Alice" # 添加元素
ZRANGE rank 0 -1 WITHSCORES # 按分数升序获取
ZREVRANK rank "Bob" # 获取元素排名(降序)
ZCOUNT rank 80 100 # 统计分数区间内的元素
应用场景
- 排行榜(游戏积分)、延迟队列(按时间戳排序)、带权重的任务调度。
6. 其他高级数据结构
6.1 位图(Bitmap)
- 本质:字符串的二进制位操作。
- 命令:
SETBIT user:login:202310 5 1 # 记录用户第5天登录 BITCOUNT user:login:202310 # 统计当月登录天数
- 应用:用户活跃度统计、布隆过滤器。
6.2 HyperLogLog
- 特点:用于基数统计(估算不重复元素数量),误差率约 0.81%。
- 命令:
PFADD ip_visitors "192.168.1.1" PFCOUNT ip_visitors # 估算唯一IP数
- 应用:大规模去重统计(如UV)。
6.3 地理空间(GEO)
- 底层:基于
ZSet
实现,存储经纬度。 - 命令:
GEOADD cities 116.40 39.90 "Beijing" GEODIST cities "Beijing" "Shanghai" km # 计算距离
- 应用:附近的人、地理位置搜索。
6.4 流(Stream,Redis 5.0+)
- 特点:持久化的消息队列,支持消费者组。
- 命令:
XADD mystream * field1 "value1" # 添加消息 XREAD COUNT 10 STREAMS mystream 0 # 读取消息
- 应用:事件溯源、日志收集。
7. 数据结构选择总结
数据结构 | 特点 | 典型场景 |
---|---|---|
String | 简单键值对 | 缓存、计数器 |
List | 有序、支持双向操作 | 消息队列、最新列表 |
Hash | 对象存储 | 用户信息、商品详情 |
Set | 无序、唯一 | 标签、共同好友 |
ZSet | 有序、唯一 | 排行榜、延迟任务 |
Bitmap | 位操作 | 用户活跃统计 |
HyperLogLog | 基数估算 | UV统计 |
Stream | 消息队列 | 事件日志、实时数据处理 |
8. 底层编码优化
Redis 根据数据量和元素类型自动选择编码方式以节省内存:
- Hash / ZSet / List:小数据量时使用
ZipList
,大数据量时转为HashTable
或SkipList
。 - Set:整数元素且数量少时使用
IntSet
,否则转为HashTable
。
9. 注意事项
- 内存优化:合理选择数据结构(如小数据用
Hash
而非多个String
)。 - 时间复杂度:关注命令的时间复杂度(如
ZRANGE
为 O(log N))。 - 持久化:RDB/AOF 对数据结构的存储效率不同。
通过合理选择数据结构和编码方式,可显著提升 Redis 性能和内存利用率。