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 哈希存储字段-值对,集合存储不重复的元素。哈希适合存储对象,集合适合存储标签、关系等。

📖 小节

📝 作业

  1. 数值操作: 使用哈希存储文章统计(阅读、点赞、评论),用HINCRBY增加计数
  2. 商品管理: 使用哈希存储商品信息,实现查看、修改、增加销量、减少库存
  3. 配置管理: 使用哈希存储用户配置,实现获取单个配置、批量获取、修改配置
  4. 性能对比: 对比使用哈希和字符串JSON存储同一对象,测试修改单个字段的步骤

下一课

下一课我们将学习 Redis 列表(上),学习列表的基本操作。

100%

🙏 帮我们做得更好

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

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