Redis 数据类型 Hash 详解与常用命令

· Redis笔记 Redis redis-cli 缓存 数据结构 NoSQL · 1 阅读 · 约 4 分钟

什么是 Hash

Redis 的 Hash 是一个键值对集合,特别适合存储对象。一个 Hash 键下可以包含多个 field,每个 field 对应一个 value,类似 Java 里的 HashMap<String, String>。

存储用户信息时,可以把用户 ID 作为 key,把姓名、年龄、邮箱等作为 field,避免把整个对象序列化成一个大字符串。

常用命令

写入与读取

# 设置单个字段
hset user:1001 name zhangsan
hset user:1001 age 25

# 批量设置
hmset user:1001 email zhangsan@example.com city beijing

# 获取单个字段
hget user:1001 name

# 批量获取
hmget user:1001 name age email

# 获取所有字段和值
hgetall user:1001

# 只获取所有 field 名
hkeys user:1001

# 只获取所有 value
hvals user:1001

删除与判断

# 删除指定字段
hdel user:1001 age

# 判断字段是否存在
hexists user:1001 name

# 查看字段数量
hlen user:1001

数值操作

# 字段值自增,步长可为负
hincrby user:1001 age 1
hincrby user:1001 age -5

# 浮点数自增
hincrbyfloat user:1001 balance 0.5

# 不存在时才设置
hsetnx user:1001 name lisi

Hash 与 String 存储对象的对比

用 String 存对象通常有两种方式:

# 整体序列化
set user:1001 "{\"name\":\"zhangsan\",\"age\":25}"

# 每个属性一个 key
set user:1001:name zhangsan
set user:1001:age 25

前者修改单个字段需要读取、反序列化、修改、再写回;后者 key 数量会爆炸,且无法统一设置过期时间。

Hash 的优势:

  • 修改单个字段只需 hset,无需读写整个对象
  • 一个 key 管理所有字段,过期、删除都是整体操作
  • 小 Hash 在底层使用 listpack(旧版本为 ziplist)编码,内存非常省

需要注意:Hash 没有针对单个 field 的过期时间,只能对整个 key 设置。

实战示例:购物车

购物车是 Hash 的典型场景,以用户 ID 为 key,商品 ID 为 field,数量为 value:

# 添加商品
hset cart:1001 2001 2

# 增加数量
hincrby cart:1001 2001 1

# 查看购物车
hgetall cart:1001

# 删除商品
hdel cart:1001 2001

代码示例(Spring Boot):

@Autowired
private StringRedisTemplate redisTemplate;

public void addToCart(String userId, String productId, int count) {
    redisTemplate.opsForHash().increment("cart:" + userId, productId, count);
}

public Map<Object, Object> getCart(String userId) {
    return redisTemplate.opsForHash().entries("cart:" + userId);
}

小结

Hash 适合存储对象和需要频繁修改部分字段的场景,例如用户信息、购物车、配置项等。数据量大且单字段很长的对象,用 String 反而更省内存,选型时结合底层编码和访问模式来判断即可。