Redis作为高性能的键值存储系统,其核心价值在于丰富的数据结构。本文将深入剖析Redis的五种基本数据类型,揭示其内部实现原理,并提供实际应用场景和最佳实践。
一、字符串(String):Redis的基石
底层实现
Redis字符串使用简单动态字符串(SDS) 结构:
struct sdshdr {
int len; // 已使用长度
int free; // 未使用空间
char buf[]; // 字节数组
};
优势特性:
-
O(1)时间复杂度获取长度
-
自动扩容机制(小于1MB时加倍,大于1MB时每次加1MB)
-
二进制安全(可存储任意格式数据)
核心命令详解
| 命令 | 时间复杂度 | 使用示例 | 说明 |
|---|---|---|---|
| SET | O(1) | SET user:1001 "Alice" | 设置键值 |
| GET | O(1) | GET user:1001 | 获取值 |
| INCR | O(1) | INCR article:2001:views | 原子递增 |
| SETEX | O(1) | SETEX session:xyz 3600 "data" | 设置带过期时间的值 |
| MSET | O(N) | MSET key1 "v1" key2 "v2" | 批量设置 |
| GETRANGE | O(N) | GETRANGE text 0 4 | 获取子串 |
二、哈希(Hash):对象存储利器
底层实现
Redis哈希使用两种编码方式:
-
ziplist(元素数量<512且值<64字节)
-
hashtable(其他情况)
// ziplist结构示例
[ zlbytes | zltail | zllen | "name" | "Alice" | "age" | "30" | zlend ]
核心命令详解
| 命令 | 时间复杂度 | 示例 | 说明 |
|---|---|---|---|
| HSET | O(1) | HSET user:1001 name "Alice" | 设置字段 |
| HGET | O(1) | HGET user:1001 name | 获取字段 |
| HGETALL | O(N) | HGETALL user:1001 | 获取所有字段 |
| HDEL | O(1) | HDEL user:1001 email | 删除字段 |
| HINCRBY | O(1) | HINCRBY user:1001 age 1 | 数值增加 |
| HSCAN | O(1) | HSCAN user:1001 0 | 渐进式遍历 |
实战应用
-
用户档案存储
HSET user:1001 name "Alice" email "alice@example.com" age 30
-
商品购物车
HINCRBY cart:1001 item:5001 2 # 添加2件商品5001
HGETALL cart:1001
三、列表(List):消息队列核心
底层实现
Redis列表使用快速列表(quicklist):
struct quicklist {
quicklistNode *head;
quicklistNode *tail;
unsigned long count; // 元素总数
// ...
};
struct quicklistNode {
quicklistNode *prev;
quicklistNode *next;
unsigned char *zl; // 指向ziplist
// ...
};
核心命令详解
| 命令 | 时间复杂度 | 示例 | 说明 |
|---|---|---|---|
| LPUSH | O(1) | LPUSH news:latest 1001 | 左端插入 |
| RPOP | O(1) | RPOP task:queue | 右端弹出 |
| LINDEX | O(N) | LINDEX news:latest 0 | 获取元素 |
| LRANGE | O(S+N) | LRANGE chat:1001 0 9 | 范围获取 |
| BLPOP | O(1) | BLPOP order:queue 30 | 阻塞弹出 |
| LTRIM | O(N) | LTRIM chat:1001 0 99 | 保留指定范围 |
应用场景
-
消息队列系统
# 生产者
LPUSH order:queue "{\"id\":1001,\"amount\":99.9}"
# 消费者
BRPOP order:queue 30
四、集合(Set):无序唯一集合
底层实现
Redis集合使用两种编码:
-
intset(元素均为整数且数量<512)
-
hashtable(其他情况)
struct intset {
uint32_t encoding; // 编码方式(INTSET_ENC_INT16等)
uint32_t length; // 元素数量
int8_t contents[]; // 元素数组
};
核心命令详解
| 命令 | 时间复杂度 | 示例 | 说明 |
|---|---|---|---|
| SADD | O(1) | SADD tags:2001 "tech" | 添加元素 |
| SISMEMBER | O(1) | SISMEMBER tags:2001 "news" | 检查存在 |
| SMEMBERS | O(N) | SMEMBERS user:1001:followers | 获取所有成员 |
| SINTER | O(N*M) | SINTER group:1 group:2 | 交集 |
| SUNION | O(N) | SUNION group:1 group:2 | 并集 |
| SSCAN | O(1) | SSCAN user:1001:followers 0 | 渐进式遍历 |
五、有序集合(Sorted Set):排行榜核心
底层实现
Redis有序集合使用两种结构:
-
ziplist(元素数量<128且值<64字节)
-
跳跃表+字典(其他情况)
struct zskiplistNode {
sds ele; // 成员
double score; // 分值
struct zskiplistNode *backward; // 后退指针
struct zskiplistLevel {
struct zskiplistNode *forward; // 前进指针
unsigned long span; // 跨度
} level[];
};
struct zset {
dict *dict; // 字典:成员->分值
zskiplist *zsl; // 跳跃表
};
核心命令详解
| 命令 | 时间复杂度 | 示例 | 说明 |
|---|---|---|---|
| ZADD | O(logN) | ZADD leaderboard 100 "Alice" | 添加成员 |
| ZRANGE | O(logN+M) | ZRANGE leaderboard 0 2 WITHSCORES | 范围查询 |
| ZREVRANK | O(logN) | ZREVRANK leaderboard "Alice" | 获取排名 |
| ZSCORE | O(1) | ZSCORE leaderboard "Alice" | 获取分数 |
| ZUNIONSTORE | O(NK)+O(MlogM) | ZUNIONSTORE out 2 set1 set2 WEIGHTS 2 3 | 有序集合并 |
| ZRANGEBYSCORE | O(logN+M) | ZRANGEBYSCORE salary 3000 5000 | 按分数范围查询 |
6万+

被折叠的 条评论
为什么被折叠?



