Redis - Hash 哈希

一、基本认识

        ⼏乎所有的主流编程语⾔都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数 组、映射。在Redis中,哈希类型是指值本⾝⼜是⼀个键值对结构,形如key="key",value={{ field1, value1 }, ..., {fieldN, valueN } },Redis 键值对和哈希类型⼆者的关系可以⽤图2-15来表⽰。

图2-15字符串和哈希类型对⽐

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

 

二、命令

2.1、HSET

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

语法:

HSET key field value [field value ...]

命令有效版本:2.0.0之后

时间复杂度:插⼊⼀组field为O(1),插⼊N组field为O(N)

返回值:添加的字段的个数。

⽰例:

 redis> HSET myhash field1 "Hello"(integer) 1redis> HGET myhash field1"Hello"

2.2、HGET

获取hash中指定字段的值。

语法:

 HGET key field

命令有效版本:2.0.0之后

时间复杂度:O(1)

返回值:字段对应的值或者nil。

⽰例:

 redis> HSET myhash field1 "foo"(integer) 1redis> HGET myhash field1"foo"redis> HGET myhash field2(nil)

2.3、HEXISTS

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

语法:

 HEXISTS key field

命令有效版本:2.0.0之后

时间复杂度:O(1)

返回值:1表⽰存在,0表⽰不存在。

⽰例:

 redis> HSET myhash field1 "foo"(integer) 1redis> HEXISTS myhash field1(integer) 1redis> HEXISTS myhash field2(integer) 0

2.4、HDEL

删除hash中指定的字段。

语法:

HDEL key field [field ...]

命令有效版本:2.0.0之后

时间复杂度:删除⼀个元素为O(1).删除N个元素为O(N)

返回值:本次操作删除的字段个数

⽰例:

 redis> HSET myhash field1 "foo"(integer) 1redis> HDEL myhash field1(integer) 1redis> HDEL myhash field2(integer) 0

2.5、HKEYS

获取hash中的所有字段。

语法:

HKEYS key

命令有效版本:2.0.0之后

时间复杂度:O(N) , N为field的个数.

返回值:字段列表。

⽰例:

 redis> HSET myhash field1 "Hello"(integer) 1redis> HSET myhash field2 "World"(integer) 1redis> HKEYS myhash1) "field1"2) "field2"

2.6、HVALS

获取hash中的所有的值。

语法:

HVALS key

命令有效版本:2.0.0之后

时间复杂度:O(N),N为field的个数.

返回值:所有的值。

⽰例:

 redis> HSET myhash field1 "Hello"(integer) 1redis> HSET myhash field2 "World"(integer) 1redis> HVALS myhash1) "Hello"2) "World"

2.7、HGETALL

获取hash中的所有字段以及对应的值。

语法:

HGETALL key

命令有效版本:2.0.0之后

时间复杂度:O(N),N为field的个数.

返回值:字段和对应的值。

⽰例:

 redis> HSET myhash field1 "Hello"(integer) 1redis> HSET myhash field2 "World"(integer) 1redis> HGETALL myhash1) "field1"2) "Hello"3) "field2"4) "World"

2.8、HMGET

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

语法:

 HMGET key field [field ...]

命令有效版本:2.0.0之后

时间复杂度:只查询⼀个元素为O(1),查询多个元素为O(N),N为查询元素个数.

返回值:字段对应的值或者nil。

⽰例:

redis> HSET myhash field1 "Hello"
(integer) 1redis> HSET myhash field2 "World"(integer) 1redis> HMGET myhash field1 field2 nofield1) "Hello"2) "World"3) (nil)

        在使⽤HGETALL时,如果哈希元素个数⽐较多,会存在阻塞Redis的可能。如果开发⼈员只 需要获取部分field,可以使⽤HMGET,如果⼀定要获取全部field,可以尝试使⽤HSCAN 命令,该命令采⽤渐进式遍历哈希类型。

2.9、HLEN

获取hash中的所有字段的个数。

语法:

HLEN key

命令有效版本:2.0.0之后

时间复杂度:O(1)

返回值:字段个数。

⽰例:

 redis> HSET myhash field1 "Hello"(integer) 1redis> HSET myhash field2 "World"(integer) 1redis> HLEN myhash(integer) 2

2.10、HSETNX

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

语法:

HSETNX key field value

命令有效版本:2.0.0之后

时间复杂度:O(1)

返回值:1表⽰设置成功,0表⽰失败。

⽰例:

 redis> HSETNX myhash field "Hello"(integer) 1redis> HSETNX myhash field "World"(integer) 0redis> HGET myhash field"Hello"

2.11、HINCRBY

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

语法:

 HINCRBY key field increment

命令有效版本:2.0.0之后

时间复杂度:O(1)

返回值:该字段变化之后的值。

⽰例:

 redis> HSET myhash field 5(integer) 1redis> HINCRBY myhash field 1(integer) 6redis> HINCRBY myhash field -1(integer) 5redis> HINCRBY myhash field -10(integer) -5

2.12、HINCRBYFLOAT

HINCRBY的浮点数版本。

语法:

 HINCRBYFLOAT key field increment

命令有效版本:2.6.0之后

时间复杂度:O(1)

返回值:该字段变化之后的值。

⽰例:

 redis> HSET mykey field 10.50(integer) 1redis> HINCRBYFLOAT mykey field 0.1"10.6"redis> HINCRBYFLOAT mykey field -5"5.6"redis> HSET mykey field 5.0e3(integer) 0redis> HINCRBYFLOAT mykey field 2.0e2"5200"

2.13、命令⼩结

        表 2-4 是哈希类型命令的效果、时间复杂度,开发⼈员可以参考此表,结合⾃⾝业务需求和数据 ⼤⼩选择合适的命令。

表 2-4 哈希类型命令⼩结

命令执⾏效果时间复杂度
hset key field value设置值O(1)
hget key field获取值O(1)
hdel key field [field ...]删除 fieldO(k), k 是 field 个数
hlen key计算 field 个数O(1)
hgetall key获取所有的 field-valueO(k), k 是 field 个数
hmget field [field ...]批量获取 field-valueO(k), k是 field 个数
hmset field value[field value...]批量获取 field-valueO(k), k是 field 个数
hexists key field判断 field 是否存在O(1)
hkeys key获取所有的 fieldO(k), k 是 field 个数
hvals key获取所有的 valueO(k), k是 field 个数
hsetnx key field value设置值,但必须在 field 不存在时才能设置成功O(1)
hincrby key field n对应 field-value+nO(1)
hincrbyfloatkey field n对应 field-value+nO(1)
hstrlen key field计算 value 的字符串⻓度O(1)

三、内部编码

哈希的内部编码有两种:

  • ziplist(压缩列表):当哈希类型元素个数⼩于hash-max-ziplist-entries配置(默认512个)、 同时所有值都⼩于hash-max-ziplist-value配置(默认64字节)时,Redis会使⽤ziplist作为哈 希的内部实现,ziplist使⽤更加紧凑的结构实现多个元素的连续存储,所以在节省内存⽅⾯⽐ hashtable更加优秀。
  • hashtable(哈希表):当哈希类型⽆法满⾜ziplist的条件时,Redis会使⽤hashtable作为哈希 的内部实现,因为此时ziplist的读写效率会下降,⽽hashtable的读写时间复杂度为O(1)。

下⾯的⽰例演⽰了哈希类型的内部编码,以及响应的变化。

1)当field个数⽐较少且没有⼤的value时,内部编码为ziplist:

 127.0.0.1:6379> hmset hashkey f1 v1 f2 v2OK127.0.0.1:6379> object encoding hashkey"ziplist"

2)当有value⼤于64字节时,内部编码会转换为hashtable:

 127.0.0.1:6379> hset hashkey f3 "one string is bigger than 64 bytes ... 省略..."OK127.0.0.1:6379> object encoding hashkey"hashtable"

3)当field个数超过512时,内部编码也会转换为hashtable:

 127.0.0.1:6379> hmset hashkey f1 v1 h2 v2 f3 v3 ... 省略 ... f513 v513OK127.0.0.1:6379> object encoding hashkey"hashtable"

四、使用场景

        图2-16为关系型数据表记录的两条⽤⼾信息,⽤⼾的属性表现为表的列,每条⽤⼾信息表现为⾏。如果映射关系表⽰这两个⽤⼾信息,则如图2-17所⽰。

图2-16关系型数据表保存⽤⼾信息

uidnameagecity
1James28Beijing
2Johnathan30Xian

图2-17映射关系表⽰⽤⼾信息

 相⽐于使⽤JSON格式的字符串缓存⽤⼾信息,哈希类型变得更加直观,并且在更新操作上变得 更灵活。可以将每个⽤⼾的id定义为键后缀,多对field-value对应⽤⼾的各个属性。

但是需要注意的是哈希类型和关系型数据库有两点不同之处:

  • 哈希类型是稀疏的,⽽关系型数据库是完全结构化的,例如哈希类型每个键可以有不同的field,⽽ 关系型数据库⼀旦添加新的列,所有⾏都要为其设置值,即使为null,如图2-18所⽰。
  • 关系数据库可以做复杂的关系查询,⽽Redis去模拟关系型复杂查询,例如联表查询、聚合查询等 基本不可能,维护成本⾼。

图2-18关系型数据库稀疏性

五、缓存⽅式对⽐

        截⾄⽬前为⽌,已经能够⽤三种⽅法缓存⽤⼾信息,下⾯给出三种⽅案的实现⽅法和优缺点 分析。

1. 原⽣字符串类型⸺使⽤字符串类型,每个属性⼀个键。

 set user:1:name Jamesset user:1:age 23set user:1:city Beijing

优点:实现简单,针对个别属性变更也很灵活。

缺点:占⽤过多的键,内存占⽤量较⼤,同时⽤⼾信息在Redis中⽐较分散,缺少内聚性,所以这种 ⽅案基本没有实⽤性。

2. 序列化字符串类型,例如JSON格式

set user:1 经过序列化后的⽤⼾对象字符串

优点:针对总是以整体作为操作的信息⽐较合适,编程也简单。同时,如果序列化⽅案选择合适,内 存的使⽤效率很⾼。

缺点:本⾝序列化和反序列需要⼀定开销,同时如果总是操作个别属性则⾮常不灵活。

3. 哈希类型

hmset user:1 name James age 23 city Beijing

优点:简单、直观、灵活。尤其是针对信息的局部变更或者获取操作。

缺点:需要控制哈希在ziplist和hashtable两种内部编码的转换,可能会造成内存的较⼤消耗。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/5263.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于python的简单web服务器示例

安装flask flask 简介:是一个用Python编写的Web应用程序框架。 它由 Armin Ronacher 开发,他领导一个名为Pocco的国际Python爱好者团队。 Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。两者都是Pocco项目 新建项目 创建好的效果 pip list 检索 安装…

职场日常:多年的测试工程师如何继续在测试行业中砥砺前行

大家好,今天我们一起聊聊测试工程师在职业、在团队、在家庭中如何更好的做好角色。 作为一个工作了多年测试工作的大牛来说,从今天开始或许未来会因为各个方面的原因可能不在从事软件测试了,但是会继续总结过往的经验,从事这么多…

【图神经网络】 AM-GCN代码实战(4)【pytorch】代码可运行

AM-GCN 网络系列 代码实践部分1. dataprocess.py1.1 模块导入1.2 特征文件生成1.3 KNN构图 2. configparser.py3. layers.py4. models.py5. utils.py6. main.py总结 代码实践部分 本专栏致力于深入探讨图神经网络模型相关的学术论文,并通过具体的编程实验来深化理解…

「Mac畅玩鸿蒙与硬件25」UI互动应用篇2 - 计时器应用实现

本篇将带领你实现一个实用的计时器应用,用户可以启动、暂停或重置计时器。该项目将涉及时间控制、状态管理以及按钮交互,是掌握鸿蒙应用开发的重要步骤。 关键词 UI互动应用时间控制状态管理用户交互 一、功能说明 在这个计时器应用中,用户…

条件logistic回归原理及案例分析

前面介绍的二元、多分类、有序Logistic回归都属于非条件Logistic回归,每个个案均是相互独立关系。在实际研究中,还有另外一种情况,即个案间存在配对关系,比如医学研究中配对设计的病例对照研究,此时违反了个案相互独立…

LeetCode:1.两数之和——Java 暴力解法哈希表

目录 题目如下: ​编辑 方法一:暴力解法 方法二:哈希表解法 题目如下: 1. 两数之和https://leetcode.cn/problems/two-sum/ 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 tar…

微信商家转账到零钱新玩法,却是个不好接受的消息

大家好,我是小悟。 深耕微信生态的小伙伴都知道,微信这个转账的功能,从一开始的“企业付款到零钱”出了有几个版本了吧。不过不管怎么变,基本都是通过openid就可以直接转账给指定用户。 为提高商户服务效率和体验,防…

C语言使用stream完成协议封送

开发过程中&#xff0c;对于自定义协议的打包&#xff0c;可以借助stream完成。 stream.h #pragma once#include <stdio.h> #include <string.h>typedef struct stream {char d[256];size_t size;size_t len;size_t pos; } stream, *pstream;void stem_init(pstr…

Window 安装ack 搜索软件 及使用

1. 先安装 PowerShell 命令行工具 2. 通过该工具安装命令行包管理器工具 Chocolatey 命令&#xff1a; Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol [System.Net.ServicePointManager]::SecurityProtocol -bor …

基于SSM的社区物业管理系统+LW参考示例

1.项目介绍 系统角色&#xff1a;管理员、业主&#xff08;普通用户&#xff09;功能模块&#xff1a;管理员&#xff08;用户管理、二手置换管理、报修管理、缴费管理、公告管理&#xff09;、普通用户&#xff08;登录注册、二手置换、生活缴费、信息采集、报事报修&#xf…

ubuntu中安装mysql

一、注意版本问题 ubuntu常用的版本是16.4&#xff0c;18.4,对应的mysql文件也不同&#xff0c;注意不要下载错误。 二、注意更换apt的源 sudo cat /etc/apt/sources.list查看现在的数据源&#xff0c;我更换了阿里的数据源。更换语句如下&#xff1a; sed -i s/http:\/\/…

2024数据库国测揭晓:安全与可靠的新标准,你了解多少?

2024年数据库国测的结果&#xff0c;于9月份的最后一天发布了。 对于数据库行业的从业者来说&#xff0c;国测是我们绕不过去的坎儿。那么什么是国测&#xff1f;为什么要通过国测&#xff0c;以及国测的要求有哪些&#xff1f; 这篇文章带大家一探究竟。 国测 自愿平等、客…

Ubuntu - 进入紧急模式,无法进入桌面

目录 一、问题 二、分析原因 三、解决 四、参考 一、问题 重新安装VMVare之后&#xff0c;将之前的虚拟机加载不进来 二、分析原因 查看系统错误日志 journalctl -xb | grep Failed mnt挂载找不到了 三、解决 查看系统错误日志 如果是磁盘错误&#xff0c;此时终端会有…

基于STM32的八位数码管显示Proteus仿真设计

基于STM32的八位数码管显示Proteus仿真设计 1.主要功能2.仿真设计3. 程序设计4. 设计报告5. 资料清单&下载链接 基于STM32的八位数码管显示Proteus仿真设计(仿真程序设计报告讲解视频&#xff09; 仿真图proteus 8.9 程序编译器&#xff1a;keil 5 编程语言&#xff1a;…

数据库管理-第257期 有好故事才能讲好故事(20241101)

数据库管理257期 2024-11-01 数据库管理-第257期 有好故事才能讲好故事&#xff08;20241101&#xff09;1 23c到23ai2 惊艳的APEX3 愿景到实现总结 数据库管理-第257期 有好故事才能讲好故事&#xff08;20241101&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文…

FreeRTOS 队列详解

目录 一、引言 二、FreeRTOS 队列的基本概念 1.定义与作用 2.队列的长度和数据大小 三、FreeRTOS 队列的特点 1.先进先出&#xff08;FIFO&#xff09;特性 2.值传递方式 3.多任务访问 4.阻塞机制 四、FreeRTOS 队列的操作方法 1.创建队列 2.写队列&#xff08;发送…

Java项目实战II基于Spring Boot的问卷调查系统的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导 一、前言 在当今信息爆炸的时代&#xff0c;问卷调查…

基于JavaWeb的宿舍管理系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

EPSON机械手与第三方相机的校准功能设计By python

EPSON机械手与第三方相机的校准功能设计By python 使用Python来实现EPSON机械手与第三方相机的校准功能是一个复杂但可行的任务。这通常涉及以下几个步骤:硬件接口通信、图像处理、标定算法实现和控制逻辑编写。 1. 环境准备 首先,库 pip install numpy opencv-python pyse…

【电子通识】白皮书、应用手册、用户指南、快速入门指南一般的定义是什么?

一般大厂家的器件或模块,除了给数据表以外,还提供应用手册、技术说明、白皮书等各种文档资料。 如下图所示为ST25 NFC/RFID标签和读卡器的文件资料:其中就有技术说明、白皮书、应用手册等。 如下所示为TI INA228技术文档相关资料: 也有应用手册、用户指南、技术文章…