第三章:数据类型详解

深入了解 Redis 的六大数据类型:String、Hash、List、Set、Zset、Stream。

最后更新: 2024-01-15
页面目录

Redis 数据类型详解

Redis 支持六种主要数据类型,每种类型都有特定的适用场景和操作命令。

数据类型概览

┌─────────────────────────────────────────────────────────────────┐
│                     Redis 六大数据类型                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  String (字符串)     ████████████████████                        │
│  ├─ 计数器           ├─ 缓存              ├─ Session            │
│                                                                  │
│  Hash (哈希)         ████████████████████                        │
│  ├─ 对象存储         ├─ 配置信息          ├─ 购物车              │
│                                                                  │
│  List (列表)         ████████████████████                        │
│  ├─ 消息队列         ├─ 文章列表          ├─ 最新动态             │
│                                                                  │
│  Set (集合)          ████████████████████                        │
│  ├─ 标签系统         ├─ 好友列表          ├─ 去重                 │
│                                                                  │
│  Zset (有序集合)     ████████████████████                        │
│  ├─ 排行榜           ├─ 优先级队列        ├─ 限流                 │
│                                                                  │
│  Stream (流)         ████████████████████                        │
│  ├─ 消息队列         ├─ 事件流            ├─ 日志收集             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

String(字符串)

String 是 Redis 最基本的数据类型,最大支持 512MB。

常用命令

# 设置值
SET key value
SET key value NX          # 不存在时设置
SET key value EX 60       # 设置过期时间(秒)
SET key value PX 60000    # 设置过期时间(毫秒)
SET key value KEEPTTL     # 保持原有 TTL

# 获取值
GET key
MGET key1 key2 key3       # 批量获取

# 自增自减
INCR key                  # +1
INCRBY key 10             # +10
DECR key                  # -1
DECRBY key 5              # -5
INCRBYFLOAT key 0.5        # +0.5(浮点数)

# 其他操作
APPEND key "suffix"       # 追加
STRLEN key                 # 长度
GETRANGE key 0 9          # 范围获取
SETRANGE key 0 "new"      # 范围设置

使用示例

# 计数器示例
SET page:view:20240115 0
INCR page:view:20240115
INCR page:view:20240115
GET page:view:20240115    # 返回: 2

# 分布式锁示例
SET lock:order:123 "uuid-xxx" NX EX 30

# Session 存储
SET user:session:abc123 "{\"userId\":1001,\"name\":\"张三\"}" EX 1800

# 验证码存储
SET verify:phone:13800138000 "123456" EX 300

内部编码

版本 小值 大值
Redis 3.0+ int embstr / raw

Hash(哈希)

Hash 是一个键值对集合,适合存储对象。

常用命令

# 设置字段
HSET key field value
HSET key field1 value1 field2 value2     # 批量设置
HSETNX key field value                   # 不存在时设置

# 获取字段
HGET key field
HMGET key field1 field2                  # 批量获取
HGETALL key                               # 获取所有字段值

# 字段操作
HDEL key field1 field2                    # 删除字段
HEXISTS key field                         # 字段是否存在
HLEN key                                  # 字段数量

# 计数操作
HINCRBY key field 1                       # +1
HINCRBYFLOAT key field 0.5                # +0.5

# 其他操作
HKEYS key                                 # 获取所有字段名
HVALS key                                 # 获取所有值
HSCAN key cursor [MATCH pattern] [COUNT n] # 迭代

使用示例

# 存储用户对象
HSET user:1001 name "张三" age "25" email "zhangsan@example.com"
HSET user:1001 city "北京" phone "13800138000"

# 获取用户信息
HGETALL user:1001
# 返回:
# 1) "name"
# 2) "张三"
# 3) "age"
# 4) "25"
# 5) "email"
# 6) "zhangsan@example.com"

# 更新年龄
HINCRBY user:1001 age 1

# 购物车示例
HSET cart:1001 item:001 '{"name":"商品A","price":99.9,"qty":2}'
HSET cart:1001 item:002 '{"name":"商品B","price":199.9,"qty":1}'
HGET cart:1001 item:001

内部编码

编码 条件
ziplist field 数量 < 512 且 value 长度 < 64 字节
hashtable 其他情况

List(列表)

List 是一个有序的字符串列表,支持两端操作。

常用命令

# 左侧操作
LPUSH key value1 value2        # 左侧插入
LPOP key                        # 左侧弹出
LPUSHX key value               # 仅当列表存在时插入
LRANGE key 0 -1                # 获取所有元素
LINDEX key 0                   # 按索引获取

# 右侧操作
RPUSH key value1 value2        # 右侧插入
RPOP key                        # 右侧弹出
RPUSHX key value               # 仅当列表存在时插入

# 阻塞操作
BLPOP key timeout              # 阻塞左侧弹出
BRPOP key timeout              # 阻塞右侧弹出
BRPOPLPUSH source dest timeout # 阻塞移动

# 其他操作
LLEN key                        # 列表长度
LINSERT key BEFORE|AFTER pivot value  # 插入
LREM key count value            # 删除元素
LTRIM key start stop           # 修剪
LSET key index value           # 设置索引值

使用示例

# 消息队列
LPUSH queue:tasks '{"job":"send_email","to":"user@example.com"}'
LPUSH queue:tasks '{"job":"gen_report","date":"2024-01-15"}'
BRPOP queue:tasks 0            # 阻塞消费

# 最新消息列表
LPUSH timeline:user:1001 "文章标题1"
LPUSH timeline:user:1001 "文章标题2"
LPUSH timeline:user:1001 "文章标题3"
LTRIM timeline:user:1001 0 99  # 只保留最新100条

# 分页获取
LRANGE timeline:user:1001 0 9   # 第1页
LRANGE timeline:user:1001 10 19 # 第2页

# 栈操作
LPUSH stack:data 1
LPUSH stack:data 2
LPUSH stack:data 3
LPOP stack:data                 # 返回 3
LPOP stack:data                 # 返回 2

内部编码

编码 条件
quicklist Redis 3.2+ 所有场景
ziplist Redis 3.2 之前,小列表
linkedlist Redis 3.2 之前,大列表

Set(集合)

Set 是一个无序的字符串集合,元素唯一。

常用命令

# 添加/删除
SADD key member1 member2        # 添加
SREM key member1 member2        # 删除
SPOP key [count]               # 随机弹出
SRANDMEMBER key count          # 随机获取(不移除)

# 查询
SMEMBERS key                    # 获取所有成员
SCARD key                       # 成员数量
SISMEMBER key member           # 是否存在
SINTER key1 key2               # 交集
SUNION key1 key2               # 并集
SDIFF key1 key2                # 差集

# 存储交集/并集/差集
SINTERSTORE dest key1 key2     # 交集并存
SUNIONSTORE dest key1 key2     # 并集并存
SDIFFSTORE dest key1 key2     # 差集并存

# 迭代
SSCAN key cursor [MATCH pattern] [COUNT n]

使用示例

# 标签系统
SADD tags:article:1001 "Redis" "数据库" "教程"
SADD tags:article:1002 "MySQL" "数据库" "教程"
SADD tags:article:1003 "Redis" "缓存" "性能"

# 获取文章的所有标签
SMEMBERS tags:article:1001

# 查找同时拥有多个标签的文章
SINTER tags:article:1001 tags:article:1003

# 查找教程类文章
SINTER tags:article:1001 tags:article:1002 tags:article:100?

# 好友列表
SADD friends:1001 2001 2002 2003
SADD friends:1002 2001 2004

# 共同好友
SINTER friends:1001 friends:1002

# UV 统计(使用 Set 实现去重)
SADD uv:20240115 "ip-192.168.1.1" "ip-192.168.1.2"
SADD uv:20240115 "ip-192.168.1.1"  # 重复,不计入
SCARD uv:20240115                    # UV 数量

Zset(有序集合)

Zset 是一个有序的字符串集合,每个元素关联一个分数。

常用命令

# 添加/删除
ZADD key score1 member1 score2 member2    # 添加
ZREM key member1 member2                  # 删除
ZINCRBY key increment member             # 增加分数

# 查询
ZRANGE key start stop [WITHSCORES]       # 按分数升序
ZREVRANGE key start stop [WITHSCORES]    # 按分数降序
ZRANGEBYSCORE key min max [WITHSCORES]   # 按分数范围
ZREVRANGEBYSCORE key max min [WITHSCORES]
ZRANK key member                          # 获取排名(升序)
ZREVRANK key member                       # 获取排名(降序)
ZSCORE key member                          # 获取分数
ZCARD key                                 # 成员数量

# 计数
ZCOUNT key min max                        # 分数范围内的数量

# 交集/并集
ZUNIONSTORE dest numkeys key1 key2 [WEIGHTS w1 w2]
ZINTERSTORE dest numkeys key1 key2 [WEIGHTS w1 w2]

# 迭代
ZSCAN key cursor [MATCH pattern] [COUNT n]

使用示例

# 排行榜
ZADD leaderboard 1500 "player:001"
ZADD leaderboard 2000 "player:002"
ZADD leaderboard 1800 "player:003"
ZADD leaderboard 2200 "player:004"

# 获取 Top 3
ZREVRANGE leaderboard 0 2 WITHSCORES
# 返回:
# 1) "player:004"
# 2) "2200"
# 3) "player:002"
# 4) "2000"
# 5) "player:003"
# 6) "1800"

# 获取玩家排名
ZREVRANK leaderboard "player:003"   # 返回 2(第3名)
ZSCORE leaderboard "player:003"     # 返回 "1800"

# 更新分数
ZINCRBY leaderboard 100 "player:003"

# 分页获取
ZREVRANGE leaderboard 0 9 WITHSCORES  # 第1页
ZREVRANGE leaderboard 10 19 WITHSCORES # 第2页

# 带权重的排行榜
ZADD science:rank 90 "Alice" 85 "Bob" 95 "Charlie"
ZADD math:rank 80 "Alice" 95 "Bob" 85 "Charlie"
# 计算总分
ZUNIONSTORE total:rank 2 science:rank math:rank
ZREVRANGE total:rank 0 -1 WITHSCORES

# 限流(滑动窗口)
ZADD rate:limit:user:1001 1705312800 "request:001"
ZREMRANGEBYSCORE rate:limit:user:1001 0 1705312740  # 删除1分钟前的
ZCARD rate:limit:user:1001                          # 当前请求数

Stream(流)

Stream 是 Redis 5.0 引入的数据类型,用于实现消息队列。

常用命令

# 添加
XADD key * field1 value1 field2 value2    # 自动生成 ID
XADD key id MAXLEN ~ 1000 * field value    # 限制长度

# 读取
XRANGE key start end [COUNT n]             # 范围读取
XREVRANGE key end start [COUNT n]          # 反向范围
XREAD [COUNT n] [BLOCK ms] STREAMS key id  # 阻塞读取
XREADGROUP GROUP g1 c1 STREAMS key ">"      # 消费组读取

# 消费组
XGROUP CREATE key group id                  # 创建消费组
XREADGROUP GROUP g1 c1 STREAMS key ">"      # 消费新消息
XACK key group id                           # 确认消息
XPENDING key group                          # 待确认消息

# 查询
XLEN key                                    # 长度
XINFO STREAM key                            # 信息

# 删除
XDEL key id1 id2                            # 删除消息
XTRIM key MAXLEN ~ count                    # 修剪

使用示例

# 创建消息流
XADD orders:stream * status "pending" amount "99.9"
XADD orders:stream * status "paid" amount "199.9"
XADD orders:stream * status "shipped" amount "199.9"

# 读取所有消息
XRANGE orders:stream - +

# 消费组模式
XGROUP CREATE orders:stream order-processors $

# 消费者读取消息
XREADGROUP GROUP order-processors consumer1 STREAMS orders:stream ">"

# 处理完成后确认
XACK orders:stream order-processors 1705312800-0

# 阻塞等待新消息
XREAD BLOCK 5000 STREAMS orders:stream $

数据类型选择指南

场景 推荐类型 原因
简单缓存 String 简单高效
Session String/Hash 灵活存储会话数据
对象存储 Hash 字段操作方便
消息队列 List/Stream 列表/流原生支持
标签系统 Set 去重,集合运算
排行榜 Zset 有序,分数排序
计数器 String INCR 原子操作
限流 Zset 时间窗口精确控制

下一步

接下来让我们学习 Redis 的核心命令。

👉 核心命令手册