Redis 数据类型概览
Redis支持5种基本数据类型,每种类型都有独特的特性和应用场景。本课概览所有数据类型。
Redis数据类型概览
| 数据类型 | 说明 | 底层实现 | 应用场景 |
|---|---|---|---|
| String(字符串) | 最基本类型,可存字符串、整数、二进制 | SDS(简单动态字符串) | 缓存、计数器、分布式锁 |
| Hash(哈希) | 键值对集合,类似Map/Object | 哈希表 + 压缩列表 | 存储对象、购物车 |
| List(列表) | 有序可重复的字符串列表 | 双向链表 + 压缩列表 | 消息队列、最新列表 |
| Set(集合) | 无序不重复的字符串集合 | 哈希表 + 整数集合 | 标签、社交关系 |
| Sorted Set(有序集合) | 有序不重复,每个元素关联分数 | 跳表 + 哈希表 | 排行榜、带权重的集合 |
💡 Redis为什么快? 所有数据都在内存中,且使用了高效的数据结构(哈希表、跳表等)。
String(字符串)
字符串是Redis最基本的数据类型,可以存储:
- 字符串(文本)
- 整数(数值)
- 二进制数据(图片、序列化对象)
特性
- 二进制安全:可以存储任意数据(包括图片、视频)
- 最大大小:512MB
- 支持数值操作:INCR、DECR、INCRBY等
- 支持位操作:SETBIT、GETBIT、BITCOUNT等
基本命令
REDIS
# 设置和获取
SET key value
GET key
# 数值操作
INCR key # 自增1
INCRBY key 10 # 自增10
DECR key # 自减1
# 其他操作
APPEND key suffix # 追加
STRLEN key # 获取长度
应用场景
| 场景 | 示例 |
|---|---|
| 缓存 | SET user:1:profile '{"name":"Alice"}' |
| 计数器 | INCR article:123:views |
| 分布式锁 | SET lock:resource "locked" NX EX 10 |
| 会话 | SET session:token123 "user_data" EX 3600 |
💡 分布式锁原理: SET命令的NX参数(仅当键不存在时设置)+ EX参数(过期时间),实现原子性的锁获取。
Hash(哈希)
哈希是一个键值对集合,类似于编程语言中的Map、Dictionary或Object。
特性
- 适合存储对象(用户信息、商品信息等)
- 可以单独修改某个字段,不需要读取整个对象
- 内存效率高(小数据量时使用压缩列表)
基本命令
REDIS
# 设置和获取字段
HSET user:1 name "Alice"
HSET user:1 age 25
HGET user:1 name # "Alice"
# 设置多个字段
HMSET user:2 name "Bob" age 30 city "Beijing"
# 获取所有字段和值
HGETALL user:2
# 1) "name"
# 2) "Bob"
# 3) "age"
# 4) "30"
# 5) "city"
# 6) "Beijing"
# 获取多个字段
HMGET user:2 name age
# 1) "Bob"
# 2) "30"
# 删除字段
HDEL user:2 city
# 检查字段是否存在
HEXISTS user:2 name # 1
# 获取所有字段名
HKEYS user:2
# 1) "name"
# 2) "age"
# 获取所有值
HVALS user:2
# 1) "Bob"
# 2) "30"
# 获取字段数量
HLEN user:2 # 2
应用场景
| 场景 | 示例 |
|---|---|
| 存储对象 | HSET user:1 name "Alice" age 25 email "alice@example.com" |
| 购物车 | HSET cart:user1 product:101 2 product:102 1(商品ID和数量) |
| 计数器组 | HINCRBY article:123 likes 1 |
Hash vs String存储对象
方式1:String存储JSON
REDIS
SET user:1 '{"name":"Alice","age":25,"email":"alice@example.com"}'
- 优点:简单
- 缺点:修改一个字段需要读取整个对象,修改,再写回
方式2:Hash存储
REDIS
HSET user:1 name "Alice" age 25 email "alice@example.com"
- 优点:可以单独修改某个字段
- 缺点:不支持复杂嵌套结构
💡 推荐: 简单对象用Hash,复杂嵌套对象用String存储JSON。
List(列表)
列表是一个有序的字符串列表,允许重复元素。
特性
- 有序:元素按插入顺序排列
- 可重复:同一个值可以出现多次
- 双端操作:可以从两端插入和弹出
- 最大长度:2^32 - 1(约42亿)
基本命令
REDIS
# 左侧插入(头部)
LPUSH mylist "a" "b" "c" # 返回列表长度
# 右侧插入(尾部)
RPUSH mylist "d" "e"
# 获取列表长度
LLEN mylist # 5
# 获取范围内的元素
LRANGE mylist 0 -1 # 获取所有元素
# 1) "c"
# 2) "b"
# 3) "a"
# 4) "d"
# 5) "e"
# 获取指定位置的元素
LINDEX mylist 0 # "c"(第一个元素)
# 左侧弹出(头部)
LPOP mylist # "c"
# 右侧弹出(尾部)
RPOP mylist # "e"
# 设置指定位置的元素
LSET mylist 0 "new"
# 删除指定值的元素
LREM mylist 1 "a" # 删除1个值为"a"的元素
应用场景
| 场景 | 说明 |
|---|---|
| 消息队列 | LPUSH + RPOP 或 RPUSH + LPOP |
| 最新列表 | 最新文章、最新评论 |
| 时间线 | 用户的朋友圈、微博时间线 |
示例:消息队列
BASH
# 生产者:推送消息到队列
LPUSH queue:email "send to user1"
LPUSH queue:email "send to user2"
# 消费者:从队列取出消息
RPOP queue:email
RPOP queue:email
# 阻塞式弹出(没有消息时阻塞)
BRPOP queue:email 10
💡 LPUSH + RPOP = 队列(FIFO),LPUSH + LPOP = 栈(LIFO)
Set(集合)
集合是一个无序的字符串集合,不允许重复元素。
特性
- 无序:元素没有顺序
- 不重复:自动去重
- 支持集合运算:交集、并集、差集
基本命令
REDIS
# 添加元素
SADD myset "a" "b" "c"
# 获取所有元素
SMEMBERS myset
# 1) "a"
# 2) "b"
# 3) "c"
# 检查元素是否存在
SISMEMBER myset "a" # 1(存在)
# 删除元素
SREM myset "a"
# 获取集合大小
SCARD myset # 2
# 随机获取一个元素
SRANDMEMBER myset
# 随机弹出一个元素
SPOP myset
集合运算
REDIS
# 创建两个集合
SADD set1 "a" "b" "c"
SADD set2 "b" "c" "d"
# 交集(同时存在于两个集合)
SINTER set1 set2
# 1) "b"
# 2) "c"
# 并集(存在于任一集合)
SUNION set1 set2
# 1) "a"
# 2) "b"
# 3) "c"
# 4) "d"
# 差集(在set1但不在set2)
SDIFF set1 set2
# 1) "a"
# 将结果存储到新集合
SINTERSTORE result set1 set2
应用场景
| 场景 | 说明 |
|---|---|
| 标签系统 | 用户标签、文章标签 |
| 社交关系 | 好友列表、关注列表 |
| 共同好友 | 两个用户好友集合的交集 |
| 推荐系统 | 可能认识的人 = 我的好友的好友 - 我的好友 - 我 |
示例:共同好友
BASH
# 用户1的好友
SADD friends:user1 "Alice" "Bob" "Charlie"
# 用户2的好友
SADD friends:user2 "Bob" "Charlie" "David"
# 共同好友
SINTER friends:user1 friends:user2
Sorted Set(有序集合)
有序集合是带分数(score)的集合,元素按分数排序。
特性
- 有序:元素按分数从小到大排序
- 不重复:元素不重复,但分数可以重复
- 支持范围查询:按分数或排名查询
基本命令
REDIS
# 添加元素(带分数)
ZADD leaderboard 100 "Alice"
ZADD leaderboard 95 "Bob"
ZADD leaderboard 98 "Charlie"
# 获取元素的分数
ZSCORE leaderboard "Alice" # "100"
# 获取元素的排名(从0开始,分数从小到大)
ZRANK leaderboard "Alice" # 2(第3名)
# 获取元素的排名(分数从大到小)
ZREVRANK leaderboard "Alice" # 0(第1名)
# 获取指定排名范围的元素(从小到大)
ZRANGE leaderboard 0 -1 WITHSCORES
# 1) "Bob"
# 2) "95"
# 3) "Charlie"
# 4) "98"
# 5) "Alice"
# 6) "100"
# 获取指定排名范围的元素(从大到小)
ZREVRANGE leaderboard 0 -1 WITHSCORES
# 1) "Alice"
# 2) "100"
# 3) "Charlie"
# 4) "98"
# 5) "Bob"
# 6) "95"
# 获取指定分数范围的元素
ZRANGEBYSCORE leaderboard 95 100 WITHSCORES
# 增加元素的分数
ZINCRBY leaderboard 5 "Bob" # Bob的分数变为100
# 删除元素
ZREM leaderboard "Bob"
# 获取集合大小
ZCARD leaderboard
# 统计指定分数范围内的元素数量
ZCOUNT leaderboard 90 100
应用场景
| 场景 | 说明 |
|---|---|
| 排行榜 | 游戏排行榜、热搜榜 |
| 带权重的标签 | 标签 + 权重 |
| 延迟队列 | 分数为执行时间戳 |
| 滑动窗口 | 时间窗口内的数据统计 |
示例:游戏排行榜
BASH
# 更新玩家分数
ZADD game:leaderboard 1500 "player1"
ZADD game:leaderboard 2300 "player2"
ZADD game:leaderboard 1800 "player3"
# 获取前10名
ZREVRANGE game:leaderboard 0 9 WITHSCORES
# 获取玩家排名
ZREVRANK game:leaderboard "player1"
# 获取分数在1000-2000之间的玩家
ZRANGEBYSCORE game:leaderboard 1000 2000 WITHSCORES
数据类型选择指南
决策树
需要存储什么?
├─ 单个值(字符串、数字、二进制)
│ └─ 使用 String
│
├─ 对象(多个字段)
│ ├─ 字段经常单独修改
│ │ └─ 使用 Hash
│ └─ 字段很少单独修改
│ └─ 使用 String(JSON)
│
├─ 有序列表
│ ├─ 需要两端操作
│ │ └─ 使用 List
│ └─ 需要按分数排序
│ └─ 使用 Sorted Set
│
└─ 无序集合
├─ 需要去重
│ └─ 使用 Set
└─ 需要去重 + 排序
└─ 使用 Sorted Set
对比总结
| 特性 | String | Hash | List | Set | Sorted Set |
|---|---|---|---|---|---|
| 有序 | - | - | ✓ | ✗ | ✓ |
| 可重复 | - | - | ✓ | ✗ | ✗ |
| 数值操作 | ✓ | ✓ | ✗ | ✗ | ✓ |
| 集合运算 | ✗ | ✗ | ✗ | ✓ | ✗ |
| 范围查询 | ✗ | ✗ | ✓ | ✗ | ✓ |
| 单字段修改 | ✗ | ✓ | ✗ | ✗ | ✗ |
TYPE命令
使用TYPE命令查看键的数据类型:
REDIS
SET mystring "hello"
TYPE mystring # string
HSET myhash field "value"
TYPE myhash # hash
LPUSH mylist "a"
TYPE mylist # list
SADD myset "a"
TYPE myset # set
ZADD myzset 1 "a"
TYPE myzset # zset
❓ 常见问题
Q String能存储多大的数据?
A 最大512MB。但建议不要存储过大的数据,会影响性能。
Q Hash和String存储对象哪个好?
A 简单对象用Hash(可以单独修改字段),复杂嵌套对象用String(存储JSON)。
Q List能存储多少元素?
A 最多2^32-1个(约42亿),但实际受内存限制。
Q Set和List的区别?
A Set无序不重复,List有序可重复。需要去重用Set,需要顺序用List。
Q Sorted Set的分数可以是小数吗?
A 可以,分数是双精度浮点数。
📖 小节
- Redis有5种基本数据类型:String、Hash、List、Set、Sorted Set
- String:最基本,可存字符串、整数、二进制
- Hash:键值对集合,适合存储对象
- List:有序列表,适合消息队列、最新列表
- Set:无序集合,支持集合运算
- Sorted Set:有序集合,适合排行榜
- 根据应用场景选择合适的数据类型
📝 作业
- 创建数据: 为每种数据类型创建一些示例数据
- TYPE命令: 使用TYPE命令验证你创建的数据类型
- 场景思考: 电商网站的商品信息、购物车、订单列表,分别用什么数据类型存储?
- 集合运算: 创建两个用户的关注列表,计算他们的共同关注
下一课
下一课我们将学习 Redis 键管理,深入了解键的操作和管理。



