第三章:数据类型详解
深入了解 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 的核心命令。
👉 核心命令手册