Redis的hash类及主要指令

文章目录

Redis的hash类及主要指令

一、hash类特点

  • hash 是一个键值对集合,类似 Java 里的 HashMap,一个 key 下面挂着多组 field-value
  • 每个 field 都是唯一的,field 可以重复写,后写的值会覆盖前面的
  • 适合存对象,比如用户信息、商品详情,比把对象序列化成 string 存进去方便得多------想改哪个字段直接改,不用整个拿出来再塞回去

二、内部实现

版本 编码 说明
7.0 之前 ziplist(压缩列表) field 和 value 交替存放在一块连续内存里,省空间,但读写要遍历,O(n)
hashtable(哈希表) 正经的哈希表结构,读写 O(1),但内存开销大
7.0 及之后 listpack(紧凑列表) 替代 ziplist 的东西,结构上更安全,解决了 ziplist 连锁更新的问题
hashtable(哈希表) 同上,大数据量时使用

什么时候会从 ziplist/listpack 转成 hashtable?

  1. field 的数量超过 hash-max-ziplist-entries(或 hash-max-listpack-entries
  2. 某个 field 或 value 的长度超过 hash-max-ziplist-value(或 hash-max-listpack-value

这两个阈值都可以在配置文件中改,默认值一般够用。简单来说就是:数据少的时候用紧凑结构省内存,数据多了自动切到哈希表保证速度。

三、常用命令

1. HSET

往 hash 里设置 field-value。可以一次设一组,也可以一次设多组。如果 field 已经存在,会覆盖旧值。

  • 语法

    HSET key field value [field value ...]

  • 返回值:新增的 field 数量(覆盖旧值的不算新增)

  • 示例

    redis> HSET user name "zhangsan"
    (integer) 1
    redis> HSET user age 25 city "beijing"
    (integer) 2
    redis> HSET user name "lisi"
    (integer) 0
    redis> HGET user name
    "lisi"

注意:从 Redis 4.0 开始,HSET 支持一次设置多个 field-value,在此之前只能用 HMSET 做批量设置。现在 HMSET 已经算是被废弃了,统一用 HSET 就行。

2. HGET

获取 hash 中某个 field 对应的 value。field 不存在返回 nil。

  • 语法

    HGET key field

  • 返回值:field 对应的 value,或者 nil

  • 示例

    redis> HSET user name "zhangsan" age 25
    (integer) 2
    redis> HGET user name
    "zhangsan"
    redis> HGET user gender
    (nil)

3. HMGET

一次性获取多个 field 的值。不存在的 field 对应位置返回 nil。

  • 语法

    HMGET key field [field ...]

  • 返回值:按顺序返回的 value 列表

  • 示例

    redis> HSET user name "zhangsan" age 25 city "beijing"
    (integer) 3
    redis> HMGET user name age gender

    1. "zhangsan"
    2. "25"
    3. (nil)

跟 mget 一个道理,批量操作减少了网络往返次数,性能比一个一个 hget 高。

4. HGETALL

把整个 hash 的所有 field-value 都拿出来。返回格式是 field1, value1, field2, value2 这样交替排列。

  • 语法

    HGETALL key

  • 返回值:field 和 value 交替的列表,key 不存在时返回空列表

  • 示例

    redis> HSET user name "zhangsan" age 25
    (integer) 2
    redis> HGETALL user

    1. "name"
    2. "zhangsan"
    3. "age"
    4. "25"

**⚠️ 注意:**HGETALL 是一个比较"重"的命令。如果 hash 里的 field 特别多(比如几万个),一次全拿出来会阻塞 Redis,还会占大量网络带宽。这种场景下建议用 HSCAN 分批拿。

5. HDEL

删除 hash 中指定的 field。可以一次删多个。

  • 语法

    HDEL key field [field ...]

  • 返回值:实际删除的 field 数量(不存在的 field 不算)

  • 示例

    redis> HSET user name "zhangsan" age 25 city "beijing"
    (integer) 3
    redis> HDEL user age city
    (integer) 2
    redis> HDEL user gender
    (integer) 0
    redis> HGETALL user

    1. "name"
    2. "zhangsan"
6. HEXISTS

判断 hash 中某个 field 是否存在。这个跟 string 的 EXISTS 不一样------EXISTS 是看 key 存不存在,HEXISTS 是看 key 里面的 field 存不存在。

  • 语法

    HEXISTS key field

  • 返回值:1 表示存在,0 表示不存在

  • 示例

    redis> HSET user name "zhangsan"
    (integer) 1
    redis> HEXISTS user name
    (integer) 1
    redis> HEXISTS user age
    (integer) 0
    redis> HEXISTS notexist name
    (integer) 0

7. HKEYS

返回 hash 中所有的 field。

  • 语法

    HKEYS key

  • 返回值:field 列表,key 不存在时返回空列表

  • 示例

    redis> HSET user name "zhangsan" age 25 city "beijing"
    (integer) 3
    redis> HKEYS user

    1. "name"
    2. "age"
    3. "city"
8. HVALS

返回 hash 中所有的 value,不返回 field。

  • 语法

    HVALS key

  • 返回值:value 列表,key 不存在时返回空列表

  • 示例

    redis> HSET user name "zhangsan" age 25 city "beijing"
    (integer) 3
    redis> HVALS user

    1. "zhangsan"
    2. "25"
    3. "beijing"
9. HLEN

返回 hash 中 field 的数量。

  • 语法

    HLEN key

  • 返回值:field 个数,key 不存在时返回 0

  • 示例

    redis> HSET user name "zhangsan" age 25
    (integer) 2
    redis> HLEN user
    (integer) 2
    redis> HLEN notexist
    (integer) 0

10. HINCRBY

把 hash 中某个 field 的值加上一个整数。field 不存在就当它是 0 开始加。值不是整数就报错。

  • 语法

    HINCRBY key field increment

  • 返回值:加完后的值

  • 示例

    redis> HSET user age 25
    (integer) 1
    redis> HINCRBY user age 1
    (integer) 26
    redis> HINCRBY user age -5
    (integer) 21
    redis> HINCRBY user score 100
    (integer) 100
    redis> HINCRBY user name 1
    (error) ERR hash value is not an integer

11. HINCRBYFLOAT

跟 HINCRBY 一样,只不过加减的是浮点数。

  • 语法

    HINCRBYFLOAT key field increment

  • 返回值:加完后的值(字符串形式)

  • 示例

    redis> HSET product price 19.9
    (integer) 1
    redis> HINCRBYFLOAT product price 0.1
    "20"
    redis> HINCRBYFLOAT product price -5.5
    "14.5"
    redis> HINCRBYFLOAT product price 2.0e1
    "34.5"

12. HSETNX

只在 field 不存在的时候才设置值,存在就不动。跟 SETNX 的思路一样。

  • 语法

    HSETNX key field value

  • 返回值:1 表示设置了,0 表示 field 已存在没设置

  • 示例

    redis> HSET user name "zhangsan"
    (integer) 1
    redis> HSETNX user name "lisi"
    (integer) 0
    redis> HSETNX user age 25
    (integer) 1
    redis> HGET user name
    "zhangsan"
    redis> HGET user age
    "25"

13. HSTRLEN

返回 hash 中某个 field 的 value 的字符串长度。跟 STRLEN 差不多,只不过作用域是 hash 里的 field。

  • 语法

    HSTRLEN key field

  • 返回值:value 的字符长度,field 或 key 不存在返回 0

  • 示例

    redis> HSET user name "zhangsan"
    (integer) 1
    redis> HSTRLEN user name
    (integer) 8
    redis> HSTRLEN user notexist
    (integer) 0

14. HRANDFIELD

随机返回 hash 中的 field。可以指定返回几个,还可以选择是否带 value 一起返回。

  • 语法

    HRANDFIELD key [count [WITHVALUES]]

  • 返回值:随机 field 的列表,带了 WITHVALUES 的话就是 field-value 交替返回

  • 示例

    redis> HSET user name "zhangsan" age 25 city "beijing"
    (integer) 3
    redis> HRANDFIELD user
    "name"
    redis> HRANDFIELD user 2

    1. "city"
    2. "age"
      redis> HRANDFIELD user 2 WITHVALUES
    3. "age"
    4. "25"
    5. "name"
    6. "zhangsan"
      redis> HRANDFIELD user -2
    7. "name"
    8. "name"

关于 count 参数:

  • count 为正数时,返回的结果不会重复
  • count 为负数时,返回的结果可能重复
  • count 超过 field 总数时,正数只返回全部(不报错),负数补齐到 |count| 个(有重复)

四、小结

  1. hash 适合存对象:比 string 序列化灵活,改哪个字段就操作哪个字段,不用整体读写
  2. 内部编码自动切换:小数据用 listpack/ziplist 省内存,大数据自动切 hashtable,一般不用手动管
  3. HGETALL 要慎用:field 太多的时候会卡,大 hash 遍历用 HSCAN
  4. 批量操作用 HMGET/HSET:跟 string 的 mget/mset 一个道理,减少网络开销
  5. 计数操作用 HINCRBY:直接操作 hash 里的数值字段,不用先读出来再加,并发场景下更安全
相关推荐
砍材农夫1 小时前
redis|spring-boot redis geo|附近定位功能
java·spring boot·redis
草莓熊Lotso1 小时前
【Redis 初阶】 从分布式演进背景到环境搭建全解析
数据库·人工智能·redis·分布式·缓存
AI-好学者1 小时前
Redis高可用与分布式架构
redis·分布式·缓存·架构
嘘神秘用10 小时前
布:AI 驱动的 Redis 客户端,更快、更直观
数据库·人工智能·redis
东北小狐狸-Hellxz12 小时前
Redis 哨兵搭建+ACL权限控制
数据库·redis
yh弓长1 天前
Redis的list类及基础指令
redis·list
智脑API平台1 天前
Codex 国内使用会封号吗?账号安全、中转站和合规边界说明
数据库·redis·缓存
迷途呀1 天前
新闻头条后端:新闻缓存模块
前端·redis·python·缓存·fastapi
记忆停留w1 天前
从单体到微服务:Redis 协同 MySQL、Milvus、MinIO 搭建企业级RAG/AI Agent脚手架架构
大数据·人工智能·redis·微服务·ai·架构·milvus