Redis 数据类型概览

Redis支持5种基本数据类型,每种类型都有独特的特性和应用场景。本课概览所有数据类型。

Redis数据类型概览

数据类型 说明 底层实现 应用场景
String(字符串) 最基本类型,可存字符串、整数、二进制 SDS(简单动态字符串) 缓存、计数器、分布式锁
Hash(哈希) 键值对集合,类似Map/Object 哈希表 + 压缩列表 存储对象、购物车
List(列表) 有序可重复的字符串列表 双向链表 + 压缩列表 消息队列、最新列表
Set(集合) 无序不重复的字符串集合 哈希表 + 整数集合 标签、社交关系
Sorted Set(有序集合) 有序不重复,每个元素关联分数 跳表 + 哈希表 排行榜、带权重的集合
💡 Redis为什么快? 所有数据都在内存中,且使用了高效的数据结构(哈希表、跳表等)。

String(字符串)

字符串是Redis最基本的数据类型,可以存储:

特性

基本命令

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(列表)

列表是一个有序的字符串列表,允许重复元素。

特性

基本命令

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 可以,分数是双精度浮点数。

📖 小节

📝 作业

  1. 创建数据: 为每种数据类型创建一些示例数据
  2. TYPE命令: 使用TYPE命令验证你创建的数据类型
  3. 场景思考: 电商网站的商品信息、购物车、订单列表,分别用什么数据类型存储?
  4. 集合运算: 创建两个用户的关注列表,计算他们的共同关注

下一课

下一课我们将学习 Redis 键管理,深入了解键的操作和管理。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏