Redis 哈希 Hash
Hash 是「字段-值」映射,像一张小表或内存版对象。存一个用户的信息,与其把 JSON 塞进 String,不如用 Hash 把 name、age 拆成字段,读改写都只动需要的部分。
写入与读取
HSET 设字段,HGET 取单个字段,HGETALL 取全部:
HSET user:1001 name zhangsan age 18 city beijing
# 输出:(integer) 3 # 新写入 3 个字段
HGET user:1001 name
# 输出:"zhangsan"
HGETALL user:1001
# 输出:1) "name" 2) "zhangsan" 3) "age" 4) "18" 5) "city" 6) "beijing"
HGETALL 是「字段值交替排列」的扁平列表,程序端通常把它转成字典对象。
批量与多字段
HMGET 一次取多字段,HSETNX 字段不存在才写入:
HMGET user:1001 name age
# 输出:1) "zhangsan" 2) "18"
HSETNX user:1001 name wangwu
# 输出:(integer) 0 # name 已存在,写入失败
HLEN user:1001
# 输出:(integer) 3 # 字段总数
字段修改与删除
HINCRBY 对数字字段原子增减,HDEL 删除指定字段:
HINCRBY user:1001 age 1
# 输出:(integer) 19
HINCRBY user:1001 score 95
# 输出:(integer) 95
HDEL user:1001 city
# 输出:(integer) 1
统计型字段(积分、余额)用 Hash 存同样支持原子自增,比整串 JSON 安全得多。
常用命令一览
| 命令 | 作用 |
|---|---|
| HSET key field value | 设置字段,可一次多个 |
| HGET key field | 取单个字段 |
| HMGET key f1 f2 | 批量取字段 |
| HGETALL key | 取全部字段与值 |
| HDEL key field | 删除字段 |
| HEXISTS key field | 字段是否存在 |
| HLEN key | 字段个数 |
| HKEYS / HVALS | 取所有字段名 / 所有值 |
| HINCRBY key field n | 字段值原子加 n |
HKEYS user:1001
# 输出:1) "name" 2) "age" 3) "score"
HVALS user:1001
# 输出:1) "zhangsan" 2) "19" 3) "95"
典型场景:购物车与对象缓存
购物车以 user 为 key、商品 ID 为字段、数量为值:
HSET cart:1001 item:88 2
# 输出:(integer) 1
HINCRBY cart:1001 item:88 1 # 再加一件
# 输出:(integer) 3
HGETALL cart:1001
# 输出:1) "item:88" 2) "3"
对象缓存同理:主键字段只读所需列,用户资料页性能远好于 String 整串方案。
易踩坑
- 字段极多(上万)时 HGETALL 会阻塞主线程,应改用 HSCAN 分批遍历;
- Hash 整体过期用 EXPIRE 作用于 key,不能单独给某个字段设过期;
- 字段名要避开冒号等特殊字符,防止与键命名规范混淆。
小结
Hash 适合「一个对象的多个字段」,写少改少、读多改多都占优。HSET/HGET/HGETALL 打底,HINCRBY 处理计数,注意大 Hash 别 HGETALL 全量拉取即可。