一、String:最灵活的瑞士军刀
1.1 数据结构揭秘
struct SDS { int len; // 已使用长度 int free; // 剩余空间 char buf[]; // 字节数组 };
特性亮点:
-
最大支持512MB数据
-
支持数值自动计算
-
可存储二进制数据
1.2 企业级应用场景
# 分布式锁实现 SET lock_key uuid NX EX 30 # 秒杀库存扣减 DECR stock_key
二、List:消息队列的基石
2.1 双端链表结构
Syntax error in graphmermaid version 8.8.3
ERROR: [Mermaid] Parse error on line 2: ... Head --> Node1[prev|value|next] Nod -----------------------^ Expecting 'SPACE', 'GRAPH', 'DIR', 'subgraph', 'SQE', 'end', 'AMP', 'TAGEND', 'START_LINK', 'STYLE', 'LINKSTYLE', 'CLASSDEF', 'CLASS', 'CLICK', 'DOWN', 'UP', 'DEFAULT', 'NUM', 'COMMA', 'ALPHA', 'COLON', 'MINUS', 'BRKT', 'DOT', 'PCT', 'TAGSTART', 'PUNCTUATION', 'UNICODE_TEXT', 'PLUS', 'EQUALS', 'MULT', 'UNDERSCORE', got 'PIPE'
实现机制:
-
元素数量<512且值<64字节时使用ziplist
-
否则使用linkedlist
2.2 实战场景
# 最新消息列表(朋友圈) LPUSH news:list "消息1" LTRIM news:list 0 99 # 阻塞队列实现 BRPOP order_queue 30
三、Hash:对象存储专家
3.1 ziplist到hashtable的跃迁
| 存储条件 | 编码类型 | |---------------------------|-----------| | field数量<512且值<64字节 | ziplist | | 任意条件不满足 | hashtable |
3.2 用户画像应用
// 存储用户信息 hset user:1001 name "张三" age 28 city "北京" // 批量获取字段 hmget user:1001 name age
四、Set:去重利器
4.1 intset与hashtable转换
set-max-intset-entries 512 当元素全为整数且数量≤512时使用intset
4.2 社交应用案例
# 共同好友计算 SINTER user:1001:friends user:1002:friends # 随机抽奖 SRANDMEMBER lottery 3
五、Sorted Set:有序魔法
5.1 跳跃表揭秘
Syntax error in graphmermaid version 8.8.3
ERROR: [Mermaid] Parse error on line 2: ... L5[L5: head -> 5 -------------------... -----------------------^ Expecting 'SPACE', 'GRAPH', 'DIR', 'subgraph', 'SQE', 'end', 'AMP', 'TAGEND', 'START_LINK', 'STYLE', 'LINKSTYLE', 'CLASSDEF', 'CLASS', 'CLICK', 'DOWN', 'UP', 'DEFAULT', 'NUM', 'COMMA', 'ALPHA', 'COLON', 'MINUS', 'BRKT', 'DOT', 'PCT', 'TAGSTART', 'PUNCTUATION', 'UNICODE_TEXT', 'PLUS', 'EQUALS', 'MULT', 'UNDERSCORE', got 'LINK'
5.2 实时排行榜实现
ZADD leaderboard 98 "玩家A" 95 "玩家B" ZREVRANGE leaderboard 0 9 WITHSCORES
六、BitMap:海量数据处理专家
6.1 位操作魔法
# 用户签到统计 SETBIT sign:202310:user1001 5 1 # 月度活跃用户统计 BITOP OR total_actives sign:202310*
6.2 存储空间优势
用户量 | 传统存储 | Bitmap存储 |
---|---|---|
1000万 | 38MB | 1.19MB |
七、HyperLogLog:基数统计之王
7.1 误差率证明
标准误差 = 1.04/√m (m=16384时误差0.81%)
7.2 UV统计实战
PFADD uv:20231001 "user1" "user2" PFCOUNT uv:20231001 PFMERGE uv:202310_total uv:202310*
八、GEO:地理空间索引
8.1 附近的人实现
GEOADD users:geo 116.397128 39.916527 "用户A" GEORADIUS users:geo 116.40 39.91 5 km WITHDIST
8.2 底层数据结构
核心使用Sorted Set存储: key = 地理位置数据 score = 经度+纬度的geohash值
九、Stream:消息队列新贵
9.1 消费者组模式
消息
Stream
ConsumerGroup
Consumer1
Consumer2
Consumer3
9.2 企业级消息队列实现
# 生产者 XADD order_stream * product_id 1001 action "create" # 消费者组 XGROUP CREATE order_stream order_group $ MKSTREAM XREADGROUP GROUP order_group consumer1 COUNT 1 STREAMS order_stream >
十、五大使用原则
原则 | 说明 | 反例 |
---|---|---|
选择最紧凑的形式 | 优先ziplist、intset | 用Hash存储多个独立字段 |
关注元素完整度 | 避免过度拆分 | 用户对象拆成多个String |
控制元素数量级 | 注意阈值升级 | Set元素超过512导致性能下降 |
考虑批量操作 | 管道机制提升性能 | 循环执行1000次HSET |
预分配重要数据结构 | 初始化大对象减少扩容操作 | 动态添加大Hash字段 |
附录:数据类型选择决策树
简单键值
对象数据
有序数据
去重集合
先进先出
地理位置
消息队列
位操作
基数统计
需要存储什么数据?
String
Hash
SortedSet
Set
List
GEO
Stream
Bitmap
HyperLogLog
十一、Redis核心类型性能对比表
数据操作 | String | Hash | List | Set | ZSet |
---|---|---|---|---|---|
插入元素 | O(1) | O(1) | O(1) | O(1) | O(logN) |
范围查询 | - | - | O(N) | - | O(logN) |
删除元素 | O(1) | O(1) | O(1) | O(1) | O(logN) |
内存使用效率 | 高 | 很高 | 中 | 中 | 低 |
典型应用场景 | 缓存、计数器 | 对象存储 | 队列 | 标签 | 排行榜 |
十二、面试六连击
-
String类型value最大能存多少数据?
-
List底层链表的哪三种实现方式?
-
为什么Hash适合存储对象类型数据?
-
Set和ZSet在实现上的核心区别是什么?
-
Bitmap最大能表示多少个用户状态?
-
Redis如何保证HyperLogLog的低存储消耗?