【Redis篇】Hash的认识以及相关命令操作

目录

前言

基本命令

HSET

HGET

HEXISTS

HDEL

HKEYS

HVALS

HGETALL

HMGET

HLEN

HSETNX

HINCRBY

HINCRBYFLOAT

内部编码

高内聚,低耦合


前言

可以看出:

Redis 的 Hash 是一个键(key)下包含多个字段(field),每个字段对应一个值(value)。一个 Hash 对象就像一个存储字段-值对的小型数据集合。

  • Key:Redis 中的主键,用于标识整个 Hash 数据结构。

  • Field:Hash 内部的字段,相当于小型键。

  • Value:字段对应的值。

    哈希类型中的映射关系通常称为 field-value,用于区分 Redis 整体的键值对(key-value),注意这里的 value 是指 field 对应的值,不是键(key)对应的值,请注意 value 在不同上下文的作用。

|------------------------------|-------------------|--------------------|
| 命令 | 执⾏效果 | 时间复杂度 |
| hset key field value | 设置值 | O(1) |
| hget key field | 获取值 | O(1) |
| hdel key field field ... | 删除 field | O(k), k 是 field 个数 |
| hlen key | 计算 field 个数 | O(1) |
| hgetall key | 获取所有的 field-value | O(k), k 是 field 个数 |
| hmget field field ... | 批量获取 field-value |

|---------------------------------------|---------------------------|--------------------|
| hmset field value field value ... | 批量获取 field-value | O(k), k 是 field 个数 |
| hexists key field | 判断 field 是否存在 | O(1) |
| hkeys key | 获取所有的 field | O(k), k 是 field 个数 |
| hvals key | 获取所有的 value | O(k), k 是 field 个数 |
| hsetnx key field value | 设置值,但必须在 field 不存在时才能设置成功 | O(1) |
| hincrby key field n | 对应 field-value +n | O(1) |
| hincrbyfloat key field n | 对应 field-value +n | O(1) |
| hstrlen key field | 计算 value 的字符串⻓度 | O(1) |

基本命令

HSET

设置 hash 中指定的字段(field)的值(value)。

语法: HSET key field value field value ...

bash 复制代码
127.0.0.1:6379> hset key f1 v1
(integer) 1
127.0.0.1:6379> hset key f2 v2 f3 v3 f4 v4
(integer) 3
127.0.0.1:6379> hset key f1 111
(integer) 0
127.0.0.1:6379> hget key f1
"111"

返回值

  • 如果 field 是一个新字段(之前不存在),返回 1。
  • 如果 field 已经存在,返回 0(值被更新)。
    注意事项
  1. 字段覆盖:

    • 如果设置一个已存在的字段,其值会被直接覆盖,不会保留旧值。
  2. Key 的初始化:

    • 如果 key(Hash 对象)不存在,HSET 会自动创建一个新的 Hash 并添加字段。
  3. 推荐用法:

    • 如果需要一次性设置多个字段,可以使用 HSET 而不是循环调用多次。

HGET

获取 hash 中指定字段的值。

语法:HGET key field

bash 复制代码
127.0.0.1:6379> hget key f2
"v2"
127.0.0.1:6379> hget key f5
(nil)
127.0.0.1:6379> hget key2 f1
(nil)

返回值

  • 如果字段存在,返回字段的值。
  • 如果字段不存在,返回 nil。
  • 如果键(key)不存在,返回 nil。

HEXISTS

判断 hash 中是否有指定的字段。

语法:HEXISTS key field

bash 复制代码
127.0.0.1:6379> hexists key f1 
(integer) 1
127.0.0.1:6379> hexists key f5
(integer) 0
127.0.0.1:6379> hexists ke2 f1
(integer) 0

返回值

  • 1:如果字段存在。
  • 0 :如果字段不存在,或者 Hash(key)本身不存在。

HDEL

删除 hash 中指定的字段。
语法:HDEL key field field ...

bash 复制代码
127.0.0.1:6379> hdel key f1 
(integer) 1
127.0.0.1:6379> hdel key f2 f3 f4
(integer) 3
127.0.0.1:6379> hdel key f5
(integer) 0

返回值

  • 返回成功删除的字段数量(integer)。
  • 如果指定的字段不存在,则不会计入返回值。

HKEYS

获取 hash 中的所有字段。
语法: HKEYS key

bash 复制代码
127.0.0.1:6379> hset key f1 v1 f2 v2 f3 v3
(integer) 3
127.0.0.1:6379> hkeys key
1) "f1"
2) "f2"
3) "f3"
127.0.0.1:6379> hkeys key2
(empty array)

返回值

  • 返回一个包含所有字段名称的列表。
  • 如果 Hash 键不存在,返回一个空列表。
  • 如果键对应的值不是 Hash 类型,会报错。

HVALS

获取 hash 中的所有的值。
语法:HVALS key

bash 复制代码
127.0.0.1:6379> hvals key
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> hvals key2
(empty array)

返回值

  • 返回一个列表,包含 Hash 中所有字段的值。
  • 如果 Hash 键不存在,返回一个空列表。
  • 如果键对应的值不是 Hash 类型,会报错。

HGETALL

获取 hash 中的所有字段以及对应的值。
语法: HGETALL key

bash 复制代码
127.0.0.1:6379> hgetall key
1) "f1"
2) "v1"
3) "f2"
4) "v2"
5) "f3"
6) "v3"
127.0.0.1:6379> hgetall key2
(empty array)

返回值

  • 成功:返回哈希表中所有字段和值,格式是字段和值交替出现的列表。
  • 失败:如果键不存在,返回一个空列表。
    在使用HKEYS,HVALS HGETALL 时,如果哈希元素个数比较多,会存在阻塞 Redis 的可能。

HMGET

一次获取 hash 中多个字段的值。

语法:HMGET key field field ...

bash 复制代码
127.0.0.1:6379> hset key f1 v1 f2 v2 f3 v3 f4 v4
(integer) 4
127.0.0.1:6379> hmget key f1 f2 f3 f4 f5
1) "v1"
2) "v2"
3) "v3"
4) "v4"
5) (nil)

返回值

  • 成功 :返回对应字段的值列表。如果某个字段不存在,返回 nil
  • 失败 :如果哈希表不存在,返回一个包含 nil 的列表。

HLEN

获取 hash 中的所有字段的个数。
语法:HLEN key

bash 复制代码
127.0.0.1:6379> hlen key
(integer) 4
127.0.0.1:6379> hlen key2
(integer) 0

返回值

  • 如果哈希表存在,返回字段的数量(整数)。
  • 如果哈希表不存在,返回 0

HSETNX

在字段不存在的情况下,设置 hash 中的字段和值。

语法:HSETNX key field value

bash 复制代码
127.0.0.1:6379> hset key f1 111 f2 222 f3 333
(integer) 3
127.0.0.1:6379> hsetnx key f1 1111111
(integer) 0
127.0.0.1:6379> hsetnx key f4 444
(integer) 1
127.0.0.1:6379> hvals key
1) "111"
2) "222"
3) "333"
4) "444"

返回值

  • 1:如果字段不存在并且成功设置了值。
  • 0:如果字段已存在,未做任何更改。

HINCRBY

将 hash 中字段对应的数值添加指定的值。

语法:HINCRBY key field increment

bash 复制代码
127.0.0.1:6379> hset key f1 100 f2 200
(integer) 2
127.0.0.1:6379> hincrby key f1 10
(integer) 110
127.0.0.1:6379> hincrby key f2 -90
(integer) 110

返回值

  • 返回更新后的字段值,即递增后的新值。

HINCRBYFLOAT

HINCRBY 的浮点数版本。
语法:HINCRBYFLOAT key field increment

bash 复制代码
127.0.0.1:6379> hset key f1 100.2 f2 150.5
(integer) 2
127.0.0.1:6379> hincrbyfloat key f1 50.4
"150.60000000000000001"
127.0.0.1:6379> hincrbyfloat key f2 -50.1
"100.4"
127.0.0.1:6379> hvals key 
1) "150.60000000000000001"
2) "100.4"

内部编码

哈希的内部编码有俩种:

  • ziplist(压缩列表):当哈希类型元素个数小于 hash-max-ziplist-entries 配置(默认 512 个)、同时所有值都小于 hash-max-ziplist-value 配置(默认 64 字节)时,Redis 会使用 ziplist 作为哈希的内部实现,ziplist 使⽤更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比 hashtable 更加优秀。
  • hashtable(哈希表):当哈希类型无法满足 ziplist 的条件时,Redis 会使用 hashtable 作为哈希的内部实现,因为此时 ziplist 的读写效率会下降,而 hashtable 的读写时间复杂度为 O(1)。
bash 复制代码
127.0.0.1:6379> hset key f1 v1
(integer) 1
127.0.0.1:6379> object encoding key
"ziplist"
127.0.0.1:6379> hset key f1 sfsfsfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
(integer) 0
127.0.0.1:6379> hget key f1
"sfsfsfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
127.0.0.1:6379> object encoding key
"hashtable"

高内聚,低耦合

来谈一个题外话题,何为高内聚,低耦合?

高内聚:高内聚 是指一个模块、类或方法内部的功能紧密相关,职责单一,内部的各个部分相互协作来完成同一目标。高内聚能够提高代码的可维护性、可重用性和可扩展性。

简单来说,就是将所有有关联的东西放在一起,最后放一个指定位置,才能方便寻找。

低内聚示例:假如我是一个丢三落四的人,每次我找衣服,它可能出现的位置 可能在床上, 沙发,或者又是凳子上,桌上,甚至可能在地上 , 虽然说衣柜里面可能有一些,但是分散在各地,每次寻找它们都可能困难,如果将它们整理好,全部放进衣柜,将会大大减少我们寻找的时间。。。。

高内聚的优势

  1. 更易维护:因为每个模块都只处理一个相对独立的功能,所以修改和扩展时不会影响其他部分。

  2. 更高的可重用性:高内聚的模块通常具有较高的可重用性,因为它们的功能独立且清晰。

  3. 更易于测试:模块化和职责单一的设计使得单元测试变得更加简单。

  4. 提升代码可读性:代码结构清晰,功能分明,开发人员容易理解和使用。

低耦合: 低耦合是指系统或模块之间的依赖关系较弱,彼此之间的联系尽可能少,能够独立修改和扩展,而不影响其他部分。

简单来说,如果俩个模块/代码之间的关联关系越大 很容易相互影响,那么它们的耦合就是很大,所谓的追求低耦合,就是将每块代码模块尽可能减小相互联系,不然一出bug,将会同时影响到很多地方

高耦合示例:在一个智能家居系统中,像空调,电视,灯光,窗帘等等家居中,这些只能跟一个中央控制系统连接,假设这个控制系统出异常了,所有的家居受到了影响,导致了这些家具罢工。所有进行它们的解耦,可以将每个家居设置独立开关,不影响别的家具影响。

低耦合的优势在于提高了系统的灵活性和可维护性。各模块之间的依赖较少,修改某一部分时不易影响其他部分,减少了错误传播的风险。同时,低耦合也增强了模块的重用性和测试性,有助于系统的扩展与演进。


结语: 写博客不仅仅是为了分享学习经历,同时这也有利于我巩固知识点,总结该知识点,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进。同时也希望读者们不吝啬你们的点赞+收藏+关注,你们的鼓励是我创作的最大动力!

相关推荐
风向决定发型丶12 小时前
redis集群搭建
数据库·redis·缓存
梦想的颜色14 小时前
硬核实践:使用 Docker 部署生产级 Redis(持久化 + 安全配置 + 高可用)
redis·docker·redis持久化·docker compose·redis哨兵·rdb aof
蓝胖的四次元口袋15 小时前
Java集合(4)
java·哈希算法
宠友信息16 小时前
多端数据互通场景下Spring Boot仿小红书源码结构设计
数据库·spring boot·redis·缓存·架构
长不胖的路人甲16 小时前
Redis 缓存的数据持久化方案讲解
数据库·redis·缓存
长不胖的路人甲17 小时前
Redis 单线程为什么速度很快
数据库·redis·缓存
彦为君17 小时前
算法思维与经典智力题
java·前端·redis·算法
彦为君18 小时前
Redis最新版本特性
java·数据库·redis·算法·bootstrap
长不胖的路人甲19 小时前
Redis 数据删除策略
数据库·redis·spring
尽兴-20 小时前
Redis 为什么快?
数据库·redis·内存