redis学习-15- Redis hash哈希散列

11.hash哈希散列

  • Redis hash(哈希散列)是由字符类型的 field(字段)和 value 组成的哈希映射表结构(也称散列表),但 value 是一个键值对,是一个键值对集合。它非常类似于表格结构。在 hash 类型中,field 与 value 一一对应,且不允许重复

类似于Map集合结构:Map<key,map<key,valule>>

  • Redis hash 特别适合于存储对象。一个 filed/value 可以看做是表格中一条数据记录;而一个 key 可以对应多条数据。下面举一个例子,使用 hash 类型存储表格中的数据,这里以user为 key, id:1为字段,name:Cao为 value:
idname
1wu
2li
  • 命令实例演示:
#以user为key,设置 id+序号为字段,name+名字为值
remote:0>hmset user id:1 wu id:2 li
"OK"
# 查询 user 这个key下所有的数据,并以字符串的形式将值返回
remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"

注意:当我们对 value 进行查询时,这个值只能以字符串的形式返回。

  • 通过上述方法,我们就把表格中的数据存储在了内存中。Redis hash 的存储结构如下图所示:
    在这里插入图片描述
  • 一个 hash 类型的 key 最多可以存储 2^32-1(约 40 亿个)字段/值。同时 Redis hash 会为这个 key 额外储存一些附加的管理信息,比如这个键的类型、最后一次访问这个键的时间等,所以 hash 键越来越多时,Redis 耗费在管理信息方面的内存就越多。当 hash 类型移除最后一个元素后,该存储结构就会被自动删除,其占用内存也会被系统回收。
11.1 hash 类型
  • hash 类型是 Redis 常用数据类型之一,其底层存储结构有两种实现方式。

  • 第一种,当存储的数据量较少的时,hash 采用 ziplist 作为底层存储结构,此时要求符合以下两个条件:

    • 哈希对象保存的所有键值对(键和值)的字符串长度总和小于 64 个字节。
    • 哈希对象保存的键值对数量要小于 512 个。
  • 当无法满足上述条件时,hash 就会采用第二种方式来存储数据,也就是 dict(字典结构),该结构类似于 Java 的 HashMap,是一个无序的字典,并采用了数组和链表相结合的方式存储数据。在 Redis 中,dict 是基于哈希表算法实现的,因此其查找性能非常高效,其时间复杂度为 O(1)。

  • 哈希表又称散列表,其初衷是将数据映射到数组中的某个位置上,这样就能够通过数组下标来访问该数据,从而提高数据的查找效率。下面通过一个示例,了解一下到底什么是哈希表。

  • 现在有 1/5/8/ 三个数字,你需要把这三个数字映射到数组中,由于哈希表规定必须使用下标来访问数据,因此需要构建一个 0 到 8 的数组,如下所示:
    在这里插入图片描述

  • 如上图所示,我们把待查找的数字,在相应的下标数组上标记出来,它们之间一一对应。虽然这样做能实现元素的查找,但却很浪费存储空间,并且查找效率也不高。而如果采用哈希表的话,我们只需要申请一个长度为 3 的数组(与待查找的元素个数相同),如下图所示:在这里插入图片描述

  • 将 1/5/8 分别对数组长度 3 做取模运算,然后把它们指向运算结果对应的数组槽位,这样就把一组离散的数据映射到了连续的空间中,从而在最大限度上提高了空间的利用率,并且也提高了元素的查找效率。但是会出现一个问题,数字 5、8 映射到同一个槽位上,这样就导致其中一个数字无法查找到。上述这种情况在实际中也会遇到,我们把它称为“哈希冲突”或者“哈希碰撞”。

  • 有许多方法可以解决“哈希冲突”,比如开放地址法、链表地址法,再次散列法等,而 Redis 采用是链表地址法。这里只对链表地址法做简单介绍,这种方法就是将有冲突的数据使用链表把它们串联起来,这样即使发生了冲突,也可以将数据存储在一起,最后,通过遍历链表的方式就找到上述发生“冲突”的数据。如下所示:
    在这里插入图片描述

如果值是字符串的话,就需要通过哈希函数将字符串转换成具体的数值,然后再对其进行映射。

11.2 常用命令汇总
命令说明
HDEL key field2 [field2]用于删除一个或多个哈希表字段。
HEXISTS key field用于确定哈希表字段是否存在。
HGET key field获取 key 关联的哈希字段的值。
HGETALL key获取 key 关联的所有哈希字段值。
HINCRBY key field increment给 key 关联的哈希字段做整数增量运算 。
HINCRBYFLOAT key field increment给 key 关联的哈希字段做浮点数增量运算 。
HKEYS key获取 key 关联的所有字段。
HLEN key获取 key 中的哈希表的字段数量。
HMSET key field1 value1 [field2 value2 ]在哈希表中同时设置多个 field-value(字段-值)
HMGET key field1 [field2]用于同时获取多个给定哈希字段(field)对应的值。
HSET key field value用于设置指定 key 的哈希表字段和值(field/value)。
HSETNX key field value仅当字段 field 不存在时,设置哈希表字段的值。分布式锁场景:更新成功,version+1,否则version-1,取更新后的值
HVALS key用于获取哈希表中的所有值。
HSCAN key cursor迭代哈希表中的所有键值对,cursor 表示游标,默认为 0。

命令语法和string类型类似,只不过值是hash值

  • 存储数据的思路:微博上好友关注时间的场景,这里以用户 关注时间 作为 key(user:attentiontime),field 字段表示好友的 ID,value 则代表好友关注用户(user:12)的时间。
local:0>hmset user:attentiontime user:2 20221202 user:3 20221101 user:4 20221005
"OK"
#迭代hash的key键
local:0>hscan user:attentiontime 0
 1)  "0"
 2)    1)   "user:2"
  2)   "20221202"
  3)   "user:3"
  4)   "20221101"
  5)   "user:4"
  6)   "20221005"
#设置单个字段
local:0>hset user:attentiontime user:5 20220909
"OK"
#查询单个字段
local:0>hget user:attentiontime user:2
"20221202"
#查询所有字段
local:0>hkeys user:attentiontime
 1)  "user:2"
 2)  "user:3"
 3)  "user:4"
 4)  "user:5"
#查询所有字段的值
local:0>hvals user:attentiontime
 1)  "20221202"
 2)  "20221101"
 3)  "20221005"
 4)  "20220909"
#查询所有字段和值
local:0>hgetall user:attentiontime
 1)  "user:2"
 2)  "20221202"
 3)  "user:3"
 4)  "20221101"
 5)  "user:4"
 6)  "20221005"
 7)  "user:5"
 8)  "20220909"
#返回字段个数
local:0>hlen user:attentiontime
"4"
#判断字段是否存在,存在返回1,不存在返回0
local:0>hexists user:attentiontime user:5
"1"
local:0>hexists user:attentiontime user:6
"0"
11.3 HSET、HGET命令
  • HSET 命令用于将哈希表 key 中的字段 field 的值设为 value。如果 key 不存在,将自动创建一个新的哈希表并进行 HSET 操作。如果 field 已经存,那么旧值将被覆盖。HSET 命令与 HMSET 命令相似,后者可以同时存储多个字段和字段值。命令可用版本:>= 2.0.0

  • Redis HGET 命令返回哈希表 key 中给定字段 field 的字段值。该命令与 HMGET 相似,后者可以返回哈希表 key 中,一个或多个给定的字段值。命令可用版本:>= 2.0.0。

  • 命令的基本语法如下:

#HSET 命令的基本语法如下:
HSET key field value
# HGET命令的基本语法如下:
HGET key field  
  • HSET命令的返回值:如果 field 是哈希表中的一个新字段,并且值设置成功,则返回 1;如果哈希表中 field 已经存在,并且旧值已被新值覆盖,则返回 0。

  • HGET 命令的返回值:给定 field 的值。当给定 filed 不存在或给定 key 不存在时,则返回 null。

  • 命令演示

remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"
# 设置一个新字段
remote:0>hset user id:3 zhao
"1"
#覆盖字段值
remote:0>hset user id:3 wang
"0"

#当字段存在时
remote:0>hget user id:3
"wang"
#当字段(域)不存在时
remote:0>hget user id:4
null
remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"
 5)  "id:3"
 6)  "wang"
11.4 HDEL命令
  • HDEL命令删除哈希表 key 中的一个或多个指定域,不存在的字段将被忽略。命令可用版本:>= 2.0.0。

注意:Redis2.4 以下的版本, HDEL 每次只能删除单个字段,如果一次性删除多个字段,请使用 Redis 事务命令 MULTI/EXEC。

  • HDEL 命令的基本语法如下:
HDEL key field [field ...]   
  • HDEL 命令返回值:被成功移除的字段的数量,不包括被忽略的字段。命令演示:
remote:0>hmset user id:4 zhao id:5 han
"OK"
remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"
 5)  "id:3"
 6)  "wang"
 7)  "id:4"
 8)  "zhao"
 9)  "id:5"
 10)  "han"
 #删除操作
 remote:0>hdel user id:4 id:5
"2"
remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"
 5)  "id:3"
 6)  "wang"
11.5 HEXISTS命令
  • HEXISTS 命令用于查看哈希表 key 中,给定域 field 是否存在。命令可用版本:>= 2.0.0。

  • Redis HEXISTS 命令的基本语法如下:

HEXISTS key field
  • HEXISTS 命令的返回值如果哈希表含有给字段,则返回 1;如果哈希表不含有给定字段,或者是 key 不存在,那么返回 0。命令演示
remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"
 5)  "id:3"
 6)  "wang"
 #存在返回1
remote:0>hexists user id:3
"1"
 #字段不存在返回0
remote:0>hexists user id:4
"0"
#key不存在返回0
remote:0>hexists users id:4
"0"
11.6 HGETALL命令
  • HGETALL 命令用于返回哈希表 key 中,所有的字段和值。命令可用版本:>= 2.0.0。

  • Redis HGETALL 命令的基本语法如下:

HGETALL key
  • HGETALL 命令的返回值:以列表形式返回哈希表的字段和字段值。若 key 不存在,则返回空列表。命令演示
remote:0>hmset user id:4 zhao id:5 han
"OK"
#返回字段与字段值
remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"
 5)  "id:3"
 6)  "wang"
 7)  "id:4"
 8)  "zhao"
 9)  "id:5"
 10)  "han"
 #key不存在
 remote:0>hgetall users
11.7 HKEYS、HVALS命令
  • HKEYS 命令返回哈希表 key 中的所有字段。HVALS 命令返回哈希表 key 中所有字段的值。命令可用版本:>= 2.0.0。

  • 命令的基本语法如下:

#HKEYS命令的基本语法如下:
HKEYS key 
#HVALS命令的基本语法如下:
HVALS key 
  • HKEYS 命令的返回值:一个包含哈希表中所有字段的列表。当 key 不存在时,返回一个空列表。

  • HVALS命令的返回值:一个包含哈希表中所有的字段值。当 key 不存在时,返回一个空列表。

  • 命令演示

remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"
 5)  "id:3"
 6)  "wang"
 7)  "id:4"
 8)  "zhao"
 9)  "id:5"
 10)  "han"
 #返回所有字段列表
 remote:0>hkeys user
 1)  "id:1"
 2)  "id:2"
 3)  "id:3"
 4)  "id:4"
 5)  "id:5"
 #key不存在时返回空列表
 remote:0>hkeys users

 #返回所有值列表
 remote:0>hvals user
 1)  "wu"
 2)  "li"
 3)  "wang"
 4)  "zhao"
 5)  "han"
  #key不存在时返回空列表
 remote:0>hvals users

11.8 HINCRBY命令
  • HINCRBY 命令为哈希表 key 中的 field 的值加上增量 increment 。增量也可以为负数,相当于对给定字段的值进行减法操作。

  • 如果 key 不存在,将自动创建一个新的哈希表并执行 HINCRBY 命令;如果域 field 不存在,那么在执行命令前,字段的值被初始化为 0。若对于一个储存字符串值的 field 执行 HINCRBY 命令将造成一个错误。该命令操作的数值被限制在 64 位(bit)有符号数字表示之内。命令可用版本:>= 2.0.0。

  • HINCRBY 命令的基本语法如下:

HINCRBY key field increment  
  • HINCRBY 命令的返回值:执行 HINCRBY 命令之后,哈希表 key 中 field 的值。命令演示
 #自动创建新的字段和值
remote:0>hincrby counter price 100
"100"
 #存在返回1
remote:0>hexists counter price
"1"
#不存在返回0
remote:0>hexists counter prices
"0"
#加减计算
remote:0>hincrby counter price 50
"150"
remote:0>hincrby counter price -50
"100"
11.9 HLEN命令
  • HLEN 命令用于返回哈希表 key 中字段的数量。命令可用版本:>= 2.0.0。HLEN 命令的基本语法如下:
HLEN key 
  • HLEN 命令的返回值:哈希表中字段的数量。若 key 不存在时,则返回 0 。命令演示
remote:0>hgetall user
 1)  "id:1"
 2)  "wu"
 3)  "id:2"
 4)  "li"
 5)  "id:3"
 6)  "wang"
 7)  "id:4"
 8)  "zhao"
 9)  "id:5"
 10)  "han"
 #返回所走字段列表
 remote:0>hkeys user
 1)  "id:1"
 2)  "id:2"
 3)  "id:3"
 4)  "id:4"
 5)  "id:5"
remote:0>hlen user
"5"
#key不存在时
remote:0>hlen users
"0"

remote:0>hscan user 0
 1)  "0"
 2)    1)   "id:1"
  2)   "wu"
  3)   "id:2"
  4)   "li"
  5)   "id:3"
  6)   "wang"
  7)   "id:4"
  8)   "zhao"
  9)   "id:5"
  10)   "han"

下一篇:redis学习-16- Redis set集合操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值