Redis 哈希(Hash)

Redis 哈希(Hash)完全攻略

“轻量级对象存储神器” —— 比 String 更省内存、更新更灵活、适合存用户、商品、配置等结构化数据。


一、Hash 核心特点

特性说明
结构key → {field1: value1, field2: value2, ...}
最大字段数4,294,967,295(约 40 亿)
每个 value 最大512 MB
内部编码ziplist(小对象) ↔ hashtable(大对象)
所有操作 O(1)增删改查极快
内存友好比 String 存对象 节省 50%+ 内存

二、Hash 命令全表(共 20+)

命令说明示例
HSET key field value设置字段HSET user:1001 name "张三"
HGET key field获取字段HGET user:1001 name
HMSET key f1 v1 f2 v2批量设置(7.0 前)→ 用 HSET
HMGET key f1 f2批量获取HMGET user:1001 name age
HGETALL key获取全部字段和值HGETALL user:1001
HDEL key field [field ...]删除字段HDEL user:1001 temp
HINCRBY key field n字段自增整数HINCRBY user:1001 score 10
HINCRBYFLOAT key field 1.5浮点数自增HINCRBYFLOAT user:1001 balance 9.9
HEXISTS key field字段是否存在HEXISTS user:1001 name
HLEN key字段数量HLEN user:1001
HKEYS key所有字段名HKEYS user:1001
HVALS key所有值HVALS user:1001
HSTRLEN key field字段值长度HSTRLEN user:1001 name
HSETNX key field value不存在才设置HSETNX user:1001 status "new"
HSCAN key cursor [MATCH pattern]渐进式遍历HSCAN user:1001 0 MATCH *na*

三、核心实战场景


1. 用户信息存储(最经典)

HSET user:1001 name "李四" age 28 email "li@example.com" score 95.5
HINCRBY user:1001 age 1
HGETALL user:1001
# 1) "name" 2) "李四" 3) "age" 4) "29" 5) "email" ...

比 String 存 JSON 节省 60% 内存!


2. 商品属性

HSET product:2001 name "Redis 实战" price 79.9 stock 100 tags "cache,db"
HINCRBY product:2001 stock -1
HGET product:2001 price

3. 配置中心

HSET config:api rate_limit 1000 timeout 30
HGET config:api rate_limit
HINCRBY config:api rate_limit 500

4. 购物车(小型)

HSET cart:1001 item:1 2 item:2 1   # 商品1买2个,商品2买1个
HINCRBY cart:1001 item:1 1        # 再加1个
HGETALL cart:1001

大型购物车建议用 Hash + List 或数据库


5. 动态统计面板

HINCRBY dashboard:20251112 pv 1
HINCRBY dashboard:20251112 uv 1
HINCRBY dashboard:20251112 error 1

四、Hash vs String 对比(何时用哪个?)

对比项HashString
存储对象推荐存 JSON
部分更新支持(只改一个 field)需重写整个值
内存占用更省(小对象用 ziplist)更大
字段多于 100 个推荐不推荐
需要原子递增字段支持 HINCRBY需 Lua
简单值/大文本不推荐推荐

结论对象用 Hash,纯文本/大 JSON 用 String


五、内部编码优化(ziplist vs hashtable)

# 小 Hash → ziplist(省内存)
HSET small:1 a 1 b 2 c 3
OBJECT ENCODING small:1   → "ziplist"

# 大 Hash → hashtable
HSET large:1 {1..1000 fields}
OBJECT ENCODING large:1   → "hashtable"

切换阈值(hash-max-ziplist-entries

配置默认值说明
hash-max-ziplist-entries512字段数 > 512 → hashtable
hash-max-ziplist-value64单个 value > 64 字节 → hashtable

生产建议:保持默认,或调大到 1024 提升性能


六、性能与内存优化建议

建议说明
控制字段数量 < 1000避免 hashtable 扩容
避免超大 value>1MB 建议用 String 或分片
使用 Pipeline批量 HSET/HMGET
设置 TTL 到 keyEXPIRE user:1001 86400
HSCAN 替代 HGETALL大 Hash 遍历用 HSCAN
# Pipeline 批量更新
pipe = r.pipeline()
pipe.hset('user:1', 'score', 100)
pipe.hset('user:1', 'level', 5)
pipe.expire('user:1', 3600)
pipe.execute()

七、大 key 排查与拆分

排查大 Hash

redis-cli --bigkeys
# 输出:Biggest hash found "user:stats" with 50000 fields

拆分方案

# 原:HSET user:1001 profile:...  stats:...  prefs:...
# 拆:
HSET user:1001:profile name "张三" age 25
HSET user:1001:stats login_count 10 last_login 1734028800
HSET user:1001:prefs theme "dark" lang "zh"

八、一键速查表

# 基础操作
HSET u:1 name "张三" age 25
HGET u:1 name
HGETALL u:1
HDEL u:1 temp

# 批量
HMGET u:1 name age email
HINCRBY u:1 age 1

# 遍历(安全)
HSCAN u:1 0 MATCH *na* COUNT 10

# 管理
HLEN u:1
HEXISTS u:1 name
HKEYS u:1
HVALS u:1

九、客户端代码示例

Python (redis-py)

import redis
r = redis.Redis()

# 创建用户
r.hset('user:1001', mapping={
    'name': '王五',
    'age': 30,
    'score': 98.5
})

# 更新分数
r.hincrby('user:1001', 'score', 1.5)

# 获取部分字段
info = r.hmget('user:1001', 'name', 'score')
print(info)  # [b'王五', b'100.0']

# 设置过期
r.expire('user:1001', 3600)

Go (go-redis)

ctx := context.Background()
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})

rdb.HSet(ctx, "user:1001", map[string]interface{}{
    "name": "李四", "age": 28,
})
rdb.HIncrBy(ctx, "user:1001", "age", 1)

十、常见问题与解决方案

问题原因解决方案
内存暴涨Hash 字段太多拆分 + TTL
HGETALL 卡顿字段 > 10万改用 HSCAN
字段冲突命名不规范统一前缀
更新慢频繁全量 HGETALL缓存热点字段

十一、Hash 在高并发场景中的妙用

1. 原子更新多个字段

# 事务(不推荐,性能差)
MULTI
HSET u:1 a 1
HSET u:1 b 2
EXEC

# 推荐:Pipeline + HSET

2. 结合 Lua 实现复杂逻辑

EVAL "
  local user = KEYS[1]
  local score = redis.call('HINCRBY', user, 'score', ARGV[1])
  if score > 1000 then
    redis.call('HSET', user, 'level', 'VIP')
  end
  return score
" 1 user:1001 10

完成!你已精通 Redis Hash!

# 一行命令体验 Hash 全功能
redis-cli <<EOF
HSET u:1 name "Redis" age 7
HINCRBY u:1 age 1
HGETALL u:1
HLEN u:1
HSCAN u:1 0
EXPIRE u:1 60
EOF

下一步推荐

  1. Redis List 队列实战
  2. Hash + Lua 实现复杂业务逻辑
  3. 大 Hash 拆分与内存优化

需要我送你

  • “用户中心完整 Hash 设计方案”
  • “高性能配置中心(Hash + 热加载)”
  • “购物车系统(Hash + ZSet)”

回复:用户中心 | 配置中心 | 购物车 即可!

文章已创建 2481

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部