48、Redis哈希操作:HSET/HGET、HMSET/HMGET、HGETALL、HDEL、HINCRBY

各位好,今天我们来聊聊Redis里最常用的数据结构之一——哈希(Hash)。

说实话,我在做嵌入式项目时,哈希用得比字符串还多。为什么呢?因为它太适合存「对象」了。你想想看,一个用户信息、一个设备状态、一个配置项……用哈希存,既清晰又高效。

哈希是什么?

Redis的哈希,说白了就是一个键值对集合。它像C语言里的结构体,也像一张小型的映射表。

# 一个哈希的结构
user:1001 -> {
    "name": "张三",
    "age": "28",
    "city": "北京"
}

每个哈希可以存最多2^32-1个字段,够你用了吧?

HSET 和 HGET:最基础的操作

这两个命令是哈希操作的基石。HSET用来设置字段值,HGET用来读取。

# 设置一个字段
HSET user:1001 name "张三"

# 读取这个字段
HGET user:1001 name
# 返回: "张三"

我在项目中遇到过一个问题:用HSET时,如果字段已经存在,它会覆盖旧值并返回0。这个返回值其实挺有用的——你可以用它判断是「新增」还是「更新」。

小技巧:HSET返回1表示新增字段,返回0表示覆盖旧值。这个特性可以用来做简单的「首次写入」判断。

HMSET 和 HMGET:批量操作省时间

一次设一个字段太慢了。尤其是你要存一个对象时,字段可能有十几个。这时候就该HMSET上场了。

# 批量设置
HMSET user:1001 name "张三" age "28" city "北京" phone "138xxxx"

# 批量读取
HMGET user:1001 name age city
# 返回: "张三" "28" "北京"

我个人习惯用HMSET来初始化一个对象。一次网络往返,搞定所有字段。效率比循环HSET高太多了。

注意:Redis 4.0.0之后,HMSET被标记为「过时」。官方推荐直接用HSET,因为它已经支持多字段了。不过HMSET还能用,老项目里很常见。

HGETALL:一把抓出所有数据

有时候你需要整个哈希的所有字段和值。HGETALL就是干这个的。

# 获取所有字段和值
HGETALL user:1001
# 返回: "name" "张三" "age" "28" "city" "北京" "phone" "138xxxx"

注意,它返回的是交替排列的字段名和字段值。在C语言里解析时,记得按「键-值-键-值」的顺序读。

我曾经在调试一个设备状态监控程序时,发现HGETALL返回的数据量太大,导致网络缓冲区溢出。嗯,这里要注意:如果哈希很大(比如上千个字段),HGETALL会一次性返回所有数据,小心内存和带宽。

HDEL:删除字段

哈希里的字段可以单独删除,不用删整个键。

# 删除一个字段
HDEL user:1001 phone

# 删除多个字段
HDEL user:1001 age city

HDEL返回被删除字段的数量。如果字段不存在,它不会报错,只是返回0。

核心要点:HDEL只删除哈希里的字段,不会删除整个键。如果你想删整个键,用DEL命令。

HINCRBY:原子自增

这个命令我特别喜欢。它让哈希里的数字字段可以原子性地增加。

# 初始值
HSET user:1001 score 100

# 增加50
HINCRBY user:1001 score 50
# 返回: 150

# 减少30(用负数)
HINCRBY user:1001 score -30
# 返回: 120

为什么说它重要?因为它是原子操作。在多线程或多客户端环境下,你不用加锁就能安全地更新计数器。

我记得有一次做在线用户统计,用HINCRBY来记录每个用户的登录次数。并发量很大,但从来没出过数据不一致的问题。原子操作就是省心。

知识体系图

下面这张图帮你理清Redis哈希操作的整体脉络:

Redis 哈希操作 写入操作 HSET:设置单个字段 HMSET:批量设置字段 读取操作 HGET:读取单个字段 HMGET:批量读取字段 HGETALL:读取全部 删除操作 HDEL:删除指定字段 运算操作 HINCRBY:原子自增/自减

实际应用场景

哈希在嵌入式系统里特别实用。我给你列几个我亲手做过的例子:

  • 设备配置存储:每个设备一个哈希,字段就是配置项名。用HGETALL读取全部配置,用HSET修改单个参数。
  • 传感器数据缓存:用HINCRBY累加传感器计数,用HGET读取当前值。
  • 用户会话管理:每个会话一个哈希,存登录时间、IP、权限等。用HDEL清理过期会话。

避坑指南

我踩过的坑,分享给你:

  • 哈希太大:一个哈希别超过几百个字段。否则HGETALL会变慢,内存占用也高。我建议拆成多个哈希,按业务逻辑分组。
  • 字段值类型:Redis哈希的字段值都是字符串。存数字时,HINCRBY会自动转成整数运算。但如果你用HSET存了一个非数字字符串,再用HINCRBY就会报错。
  • 内存开销:每个哈希有额外元数据。小哈希(几十个字段)用ziplist编码,省内存。大哈希会自动转成hashtable,性能更好但更占内存。
总结一下:哈希是Redis里最像「对象」的数据结构。HSET/HGET是基础,HMSET/HMGET提升效率,HGETALL用于全量读取,HDEL做精确删除,HINCRBY实现原子计数。掌握这六个命令,你就能处理大部分结构化数据的存储需求了。

好了,哈希操作就聊到这里。代码写起来其实很简单,关键是理解每个命令的适用场景。下次你存用户信息或设备状态时,试试哈希,你会发现比字符串拼接舒服多了。


公众号:蓝海资料掘金营,微信 deep3321