首页 > 数据库 >Redis---hash哈希散列

Redis---hash哈希散列

时间:2022-08-16 18:35:31浏览次数:52  
标签:10 hash key Redis --- field user 哈希

1. 前言

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

Redis hash 特别适合于存储对象。一个 filed/value 可以看做是表格中一条数据记录;而一个 key 可以对应多条数据。下面举一个例子,使用 hash 类型存储表格中的数据,这里以user为 key, id:1为字段,name:Cao为 value:

用户表格
idname
1 Cao
2 Zhao

命令实例演示:

#以user为key,设置 id+序号为字段,name+名字为值
127.0.0.1:6379> HMSET user id:1 name:Cao id:2 name:Zhao
OK
# 查询 user 这个key下所有的数据,并以字符串的形式将值返回
127.0.0.1:6379> HGETALL user
1) "id:1"
2) "name:Cao"
3) "id:2"
4) "name:Zhao"

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

通过上述方法,我们就把表格中的数据存储在了内存中。Redis hash 的存储结构如下图所示:

redis hash存储结构示意图
图1:hash存储结构图 一个 hash 类型的 key 最多可以存储 2^32-1(约 40 亿个)字段/值。同时 Redis hash 会为这个 key 额外储存一些附加的管理信息,比如这个键的类型、最后一次访问这个键的时间等,所以 hash 键越来越多时,Redis 耗费在管理信息方面的内存就越多。当 hash 类型移除最后一个元素后,该存储结构就会被自动删除,其占用内存也会被系统回收。

2. 初识hash类型

hash 类型是 Redis 常用数据类型之一,其底层存储结构有两种实现方式。

第一种,当存储的数据量较少的时,hash 采用 ziplist 作为底层存储结构,此时要求符合以下两个条件:
  • 哈希对象保存的所有键值对(键和值)的字符串长度总和小于 64 个字节。
  • 哈希对象保存的键值对数量要小于 512 个。

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

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

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

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

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

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

链表寻址

如果值是字符串的话,就需要通过哈希函数将字符串转换成具体的数值,然后再对其进行映射。关于哈希函数这里不做过多介绍,如果感兴趣可以自行研究。

3. 常用命令汇总

hash常用命令汇总
命令    说明
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 不存在时,设置哈希表字段的值。
HVALS key    用于获取哈希表中的所有值。
HSCAN key cursor     迭代哈希表中的所有键值对,cursor 表示游标,默认为 0。

4. 基本命令操作

示例演示:微博上好友关注时间的场景,这里以用户 ID 作为 key(user:10),field 字段表示好友的 ID,value 则代表好友关注用户(user:10)的时间。

#设置单个字段
127.0.0.1:6379> HSET user:10 user:1 20201001
(integer) 1
#同时设置多个字段
127.0.0.1:6379> HMSET user:10 user:2 20201002 user:3 20201004 user:4 20201018
OK
#查询单个字段
127.0.0.1:6379> HGET user:10 user:2
"20201002"
#查询所有字段
127.0.0.1:6379> HGETALL user:10
1) "user:1"
2) "20201001"
3) "user:2"
4) "20201002"
5) "user:3"
6) "20201004"
7) "user:4"
8) "20201018"
127.0.0.1:6379> HKEYS user:10
1) "user:1"
2) "user:2"
3) "user:3"
4) "user:4"
#返回字段个数
127.0.0.1:6379> HLEN user:10
(integer) 4
#返回所有字段值
127.0.0.1:6379> HVALS user:10
1) "20201001"
2) "20201002"
3) "20201004"
4) "20201018"
#迭代hash的key键
127.0.0.1:6379> HSCAN user:10 0
1) "0"
2) 1) "user:1"
   2) "20201001"
   3) "user:2"
   4) "20201002"
   5) "user:3"
   6) "20201004"
   7) "user:4"
   8) "20201018"
#判断字段是否存在,存在返回1,不存在返回0
127.0.0.1:6379> HEXISTS user:10 user:4
(integer) 1
127.0.0.1:6379> HEXISTS user:10 user:5
(integer) 0

 

标签:10,hash,key,Redis,---,field,user,哈希
From: https://www.cnblogs.com/jiajunling/p/16592523.html

相关文章

  • Linux--cheat命令详解
    今天给大家介绍一个Linux超级实用命令,有了这个命令,你就可以愉快使用Linux上几乎所有常用命令了,再也不用担心记不住那么多选项啦~我们知道,Linux系统总共有300~500个......
  • Redis---set集合
    1.前言Redisset(集合)遵循无序排列的规则,集合中的每一个成员(也就是元素,叫法不同而已)都是字符串类型,并且不可重复。Redisset是通过哈希映射表实现的,所以它的添加、删除......
  • 算法-实验一
    算法设计与分析实验一第一题公元5世纪,我国古代数学家张丘建在他所撰写的《算经》中,提出了这样的一个问题:“鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。百钱买百鸡,问鸡翁、......
  • qt5.9 +vs2015 32bit 错误“-1: error: LNK1158: 无法运行“rc.exe”
    开发平台qt5.9.0+vs201532bit....在准备运行vs2015及安装了vs2019后,运行原来可以运行的程序时,出现了错误“-1:error:LNK1158:无法运行“rc.exe”复制了“C:\Progra......
  • Linux -服务器磁盘 Raid & 分区 & 挂载
     流计算服务器  流处理服务器 有一台流处理服务器(系统盘:2*600G、数据盘:6*600G)分区挂载如下: 设备名称分区大小挂载点文件系统类型磁盘用......
  • Redis---列表
    1.前言Redislist(列表)相当于Java语言中的LinkedList结构,是一个链表而非数组,其插入、删除元素的时间复杂度为O(1),但是查询速度欠佳,时间复杂度为O(n)。当向列表中添......
  • 汽车外观vr场景展示的优势-深圳华锐视点
    在汽车品牌营销预算和效果都大打折扣的背景下,汽车市场营销正偏向性价比高的效果营销渠道,比如以新兴VR虚拟现实制作的车辆VR互动展示系统,成为车辆展销会线上化的补充和......
  • Webpack 打包 - 5.webpack 打包其它资源
    1.素材准备:首先准备一些矢量图图标,如,阿里矢量图等。(阿里矢量官网:https://www.iconfont.cn/)随便找一些icon下载到本地  解压出来是这样的 2.文件结构 ......
  • Financial - 情景分析中的“曲线-PCA”是怎么工作的?
    from天翼老师背景描述:假设某个曲线上有10个期限点(term),我们要会看过去100天的这条曲线的变化。 计算过程:1)这是第1天,与第0天之间,每个期限点的变化:△0f(t)=[f1(t1)......
  • CSP-J 2022备战——树的基础
    前身树,顾名思义,是一种植物一些基本概念:根节点:树上任意一点都可以被定义成根节点,也就是所有点的祖先祖节点(祖先):在某节点的上层,且跟该节点有直接联系的点父节点(父亲):在子......