Redis 哈希(下)
本课学习哈希的数值操作、迭代查询等高级功能。
HINCRBY:字段数值增加
哈希字段可以存储数字字符串,并支持原子性的数值操作。
HINCRBY:整数增加
REDIS
# 创建文章统计信息
HSET article:123 views 1000 likes 50 comments 20
# 增加阅读数
HINCRBY article:123 views 1
(integer) 1001
# 增加点赞数
HINCRBY article:123 likes 1
(integer) 51
# 批量增加
HINCRBY article:123 views 10
(integer) 1011
# 减少数值(传负数)
HINCRBY article:123 likes -1
(integer) 50
HINCRBYFLOAT:浮点数增加
REDIS
# 商品价格
HSET product:2001 price 99.99
# 增加价格
HINCRBYFLOAT product:2001 price 10.5
"110.49"
# 降低价格(传负数)
HINCRBYFLOAT product:2001 price -5.0
"105.49"
应用场景:计数器组
REDIS
# 用户统计信息
HSET user:stats:1 posts 0 followers 0 following 0
# 发表文章
HINCRBY user:stats:1 posts 1
# 获得粉丝
HINCRBY user:stats:1 followers 1
# 关注他人
HINCRBY user:stats:1 following 1
# 查看统计
HGETALL user:stats:1
💡 优势: 使用哈希存储多个计数器,比使用多个字符串键更节省内存。
HSCAN:迭代查询大哈希
当哈希字段很多时,使用HGETALL会一次性返回所有数据,可能阻塞服务器。HSCAN可以分批迭代获取。
基本用法
REDIS
# 创建一个大的哈希
HSET large:hash field1 "value1" field2 "value2" ... field1000 "value1000"
# 开始迭代
HSCAN large:hash 0
1) "127" # 下一次使用的游标
2) 1) "field1"
2) "value1"
3) "field2"
4) "value2"
...
# 继续迭代
HSCAN large:hash 127
1) "0" # 游标为0表示迭代结束
2) 1) "field999"
2) "value999"
...
匹配模式
REDIS
# 只获取匹配模式的字段
HSCAN user:1 0 MATCH age*
1) "0"
2) 1) "age"
2) "25"
指定每次返回数量
REDIS
# 每次返回约100个字段
HSCAN large:hash 0 COUNT 100
💡 用途: HSCAN适合遍历大哈希,不会阻塞服务器,可以分批处理。
哈希高级应用
场景1:电商商品详情
REDIS
# 存储商品完整信息
HSET product:3001 \
name "iPhone 15 Pro" \
brand "Apple" \
price 8999 \
stock 100 \
category "phone" \
sales 0 \
rating 4.8
# 查看商品基本信息
HMGET product:3001 name price stock
# 增加销量
HINCRBY product:3001 sales 1
# 减少库存
HINCRBY product:3001 stock -1
# 更新评分
HSET product:3001 rating 4.9
# 检查库存
HGET product:3001 stock
场景2:用户配置
REDIS
# 存储用户配置
HSET user:config:1 \
theme "dark" \
language "zh" \
notifications "on" \
privacy "public" \
timezone "Asia/Shanghai"
# 获取单个配置
HGET user:config:1 theme
# 修改配置
HSET user:config:1 theme "light"
# 批量获取配置
HMGET user:config:1 theme language notifications
场景3:实时统计
REDIS
# 网站今日统计
HSET stats:20260623 \
page_views 0 \
unique_visitors 0 \
new_users 0 \
orders 0 \
revenue 0.0
# 增加页面浏览
HINCRBY stats:20260623 page_views 1
# 增加独立访客
HINCRBY stats:20260623 unique_visitors 1
# 增加订单
HINCRBY stats:20260623 orders 1
# 增加收入
HINCRBYFLOAT stats:20260623 revenue 299.99
# 查看统计
HGETALL stats:20260623
场景4:AB测试配置
REDIS
# 存储实验配置
HSET experiment:homepage \
button_color "blue" \
layout "grid" \
show_banner "yes" \
discount_rate 0.1
# 获取实验配置
HGET experiment:homepage button_color
# 更新实验配置
HSET experiment:homepage button_color "red"
哈希与JSON对比
存储方式对比
方式1:哈希
REDIS
HSET user:1 name "Alice" age 25 email "alice@example.com"
方式2:字符串JSON
REDIS
SET user:1 '{"name":"Alice","age":25,"email":"alice@example.com"}'
操作对比
| 操作 | 哈希 | 字符串JSON |
|---|---|---|
| 获取单个字段 | HGET user:1 name |
需要解析JSON |
| 修改单个字段 | HSET user:1 age 26 |
读取→解析→修改→序列化→写回 |
| 获取所有字段 | HGETALL user:1 |
GET user:1 + 解析JSON |
| 数值操作 | HINCRBY user:1 age 1 |
需要解析→修改→序列化 |
| 内存占用 | 较小 | 较大(JSON格式开销) |
适用场景对比
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 用户资料 | 哈希 | 字段独立,频繁修改 |
| 商品信息 | 哈希 | 字段独立,部分更新 |
| 复杂嵌套对象 | 字符串JSON | 哈希不支持嵌套 |
| 数组数据 | 字符串JSON | 哈希不支持数组 |
| 配置对象 | 哈希 | 字段独立,查询快 |
💡 选择原则:
- 字段独立、频繁部分更新 → 哈希
- 复杂嵌套、需要数组 → 字符串JSON
- 需要数值操作 → 哈希
性能优化
1. 避免大哈希
REDIS
# ❌ 不推荐:单个哈希存储大量字段
HSET big:hash field1 ... field10000
# ✅ 推荐:分片存储
HSET hash:part1 field1 ... field1000
HSET hash:part2 field1001 ... field2000
2. 使用HSCAN代替HGETALL
REDIS
# ❌ 大哈希使用HGETALL
HGETALL large:hash # 可能阻塞
# ✅ 使用HSCAN迭代
HSCAN large:hash 0
3. 批量操作减少网络往返
REDIS
# ❌ 多次单独操作
HSET user:1 name "Alice"
HSET user:1 age 25
HSET user:1 city "Beijing"
# ✅ 批量操作
HSET user:1 name "Alice" age 25 city "Beijing"
4. 合理设置编码阈值
在 redis.conf 中配置:
CONF
# 哈希字段数量阈值(默认512)
hash-max-ziplist-entries 512
# 哈希字段值最大长度(默认64字节)
hash-max-ziplist-value 64
ℹ️ 了解: 增大阈值可以节省内存,但会降低性能。根据实际数据调整。
哈希限制
1. 不支持嵌套
REDIS
# ❌ 无法存储嵌套对象
HSET user:1 address '{"city":"Beijing","zip":"100000"}'
# ✅ 使用字符串存储嵌套部分
HSET user:1 city "Beijing" zip "100000"
2. 不支持数组
REDIS
# ❌ 无法存储数组
HSET user:1 tags ["redis","database","cache"]
# ✅ 使用集合或列表存储数组
SADD user:1:tags "redis" "database" "cache"
3. 字段值只能是字符串
REDIS
# 所有值都是字符串
HSET user:1 age 25
HGET user:1 age
"25" # 返回字符串,不是整数
❓ 常见问题
Q HINCRBY对非数字字段会怎样?
A 会报错:
(error) ERR hash value is not an integer。确保字段值是数字字符串。Q 哈希字段有顺序吗?
A 没有。哈希字段是无序的,HGETALL返回的顺序不保证。
Q 如何判断一个键是哈希类型?
A 使用TYPE命令:
TYPE user:1 返回 hash。Q HSCAN保证不重复吗?
A 不保证。HSCAN可能返回重复字段,应用层需要去重。
Q 哈希和集合的区别?
A 哈希存储字段-值对,集合存储不重复的元素。哈希适合存储对象,集合适合存储标签、关系等。
📖 小节
- HINCRBY/HINCRBYFLOAT对字段进行数值操作
- HSCAN迭代查询大哈希,避免阻塞
- 哈希适合存储商品、配置、统计等对象
- 哈希vs字符串JSON:哈希适合简单对象和部分更新
- 性能优化:避免大哈希、使用HSCAN、批量操作
- 哈希限制:不支持嵌套、不支持数组、值只能是字符串
📝 作业
- 数值操作: 使用哈希存储文章统计(阅读、点赞、评论),用HINCRBY增加计数
- 商品管理: 使用哈希存储商品信息,实现查看、修改、增加销量、减少库存
- 配置管理: 使用哈希存储用户配置,实现获取单个配置、批量获取、修改配置
- 性能对比: 对比使用哈希和字符串JSON存储同一对象,测试修改单个字段的步骤
下一课
下一课我们将学习 Redis 列表(上),学习列表的基本操作。



