2023.12.25 关于 Redis 数据类型 Hash 常用命令、内部编码、应用场景

目录

Hash 数据类型

Hash 操作命令

HSET

HGET

HEXISTS

HDEL

HKEYS

HVALS

HGETALL

HMGET

HLEN

HSETNX

HINCRBY

HINCRBYFLOAT

HSTRLEN

Hash 编码方式

理解什么是压缩

Hash 实际应用

Cache 缓存


Hash 数据类型

  • 整体上来说 Redis 是键值对结构,其中 key 和 value 之间通过哈希方式组织的
  • 该结构中 key 负责组织数据的结构,而 value 却可以为不同类型的数据,其中一种类型就是 哈希
  • 这就相当于在 value 中又存储了一层键值对(field - value),相当于所谓的套娃

实例理解

  • 存储一个 uid 为 1 的用户对象,姓名为 mastermao 年龄为 20

注意:

  • 当我们谈到 key ,指的是整体 Redis 键值对(key - value)结构中的 key 
  • 当我们谈到 field,指的是 Redis 中的键值对对应的值(value)中哈希表中的一个特定的键
  • 该特定键用来进一步区分 和 访问哈希表中的各个数据项

Hash 操作命令

HSET

  • 用来设置 hash 中指定的字段 field 和 value
  • 此处的(field - value)中的 value 只能为字符串类型

语法:

hset key field value [field value ...]

时间复杂度:

  • O(1)

返回值:

  • 返回值是设置成功的 键值对(field - value)的个数

 实例理解


HGET

  • 用来获取 hash 中指定字段 field 的 value 值

语法:

hget key field

时间复杂度:

  • O(1)

 实例理解

  • 紧接着上述 hset 的实例进行测试


HEXISTS

  • 用来检查 hash 中是否存在指定字段 field

语法:

hexists key field

时间复杂度:

  • O(1)

返回值:

  • 返回 1 表示存在
  • 返回 0 表示不存在

实例理解

  • 紧接着上述 hset 的实例进行测试


HDEL

  • 用来删除 hash 中指定的字段 field

语法:

hdel key field [field ...]

时间复杂度:

  • O(N)
  • 其中 N 代表删除的字段个数,一般不会很大,也可认为是 O(1)

返回值:

  • 本次操作删除的字段个数

实例理解

  • 紧接着上述 hset 的实例进行测试

注意:

  • del 删除的是 key
  • hdel 删除的是 field

HKEYS

  • 获取 hash 中的所有字段
  • 该操作会现根据 key 找到对应的 hash,然后再遍历 hash

语法:

hkeys key

时间复杂度:

  • O(N)
  • 其中 N 为 field 的个数

实例理解

  • hkeys key 命令存在一定的风险,类似于 keys * 命令
  • 主要因为我们并不知道某个 hash 中是否存在大量的 field,从而导致 Redis 被阻塞 

HVALS

  • 和上面的 hkeys 相对应,用于获取 hash 中的所有 value 

 语法:

hvals key

时间复杂度:

  • O(N)
  • 其中 N 为 field 的个数

 实例理解

注意:

  • 使用 h 系列的命令操作 key 时,必须保证 key 对应的 value 得为 哈希 类型

HGETALL

  • 用于获取 hash 中的所有字段 field 以及对应的值 value
  • 相当于 hkeys + hvals 命令的结合

语法:

hgetall key

时间复杂度:

  • O(N)
  • 其中 N 为 field 的个数

 实例理解

  • 观察此处的返回值
  • 一个 field 一个 value 交替返回

注意:

  • 上述操作风险比较大
  • 因为多数情况下 不需要查询一个 key 中所有的 field 和 value 可能只查其中的几对

HMGET

  • 用于获取 hash 中多个字段的值 value
  • 类似于 mget 可以一次查询多个 key

 语法:

hmget key field [field ...]

时间复杂度:

  • O(N)
  • 其中 N 代表查询的字段个数,一般不会很大,也可认为是 O(1)

实例理解

注意:

  • 此处 hmget 命令返回的值 value,与查询时 输入字段 field 的顺序相匹配

问题:

  • 有没有 hmset 一次可以设置多对(field - value)呢?

回答:

  • 有 hmset 命令
  • 但是并不需要使用其命令,因为 hset 已经支持一次设置多对(field - value)了

小总结:

  • 上述的 hkeys、hvals、hgetall 命令均存在一定风险
  • 如果 hash 的元素个数太多,则执行的耗时会比较长,从而阻塞掉 Redis 

补充:

  • hscan 命令可以渐进式地遍历 Redis 的 hash
  • 即敲一次命令,遍历一小部分,再敲一次命令,再遍历一小部分
  • 此时的时间是可控的,连续执行多次便可完成整个的 hash 的遍历,也就是所谓的 "化整为零"

HLEN

  • 用于获取 hash 中的所有键值对个数

语法:

​​​​​​​

hlen key

时间复杂度:

  • O(1)
  • 获取 hash 的元素个数不需要遍历

 实例理解


HSETNX

  • 字段 field 不存在的情况下,设置 hash 中的字段 field 和 值 value
  • 类似于 setnx ​​​​​​​

语法:

hsetnx key field value

时间复杂度:

  • O(1)

返回值:

  • 返回 1 表示设置成功
  • 返回 0 表示设置失败

实例理解


HINCRBY

  • hash 这里的 value 也可以被当作数字来进行处理
  • hincrby 命令用来对 value 进行加减整数
  • 因为使用频率不是特别高,Redis 没有提供 hincr、hdecr 之类的命令

 语法:

hincrby key field increment

时间复杂度:

  • O(1)

返回值:

  • value ± 之后的结果

实例理解


HINCRBYFLOAT

  • hincybyfloat 命令用来对 value 进行加减小数

 语法:

hincrbyfloat key field increment

时间复杂度:

  • O(1)

返回值:

  • value ± 之后的结果

实例理解


HSTRLEN

  • 用于计算 hash 中的值 value 的字符串长度

 语法:

hstrlen key field 

时间复杂度:

  • O(1)

返回值:

  • hash 中的值 value 的字符串长度,单位为字节

实例理解

Hash 编码方式

  • 哈希的内部编码有 两种
  1. ziplist 压缩列表
  2. hashtable 哈希表

实例理解

  • 我们通过 object encoding key 来查看编码方式


理解什么是压缩

  • 压缩的本质,就是对数据进行重写编码
  • 不同的数据有不同的特点
  • 结合这些特点,进行精妙的设计,使其能够在重新编码之后,缩小体积

实例理解

  • ' abbcccddddeeeee ' ———重新编码———> ' 1a2b3c4d5e '
  • ' abcd0000000000000000000000000000000efgh ' ———重新编码———> 'abcd0[30]efgh​​​​​​​ '

注意:

  • 上述实例是比较粗糙的编码方式
  • 实际上 一些常见的压缩算法都有着十分精妙的设计
  • ziplist 也是同理,其内部的数据结构也进行了 精心设计,其目的就是为了节省内存空间


ziplist 和 hashtable

  • 如果上来就直接使用 hashtable,那该哈希表中可能有些位置上有元素,有些位置上没有元素,从而会造成一定程度上的空间浪费
  • 所以当一开始元素个数比较少时,还是先使用 ziplist 进行编码,以达到节省空间的目的
  • 而 ziplist 作为一种内部编码方式,虽然一定程度上 节省了内存空间,但读写元素时的速度较慢
  • 这种慢 在元素较少时可能不太明显,但是当元素数量过多时,性能下降会更为明显
  • 相比之下 hashtable 的内部结构更为灵活,它可以更高效地处理大量的元素
  • 在 hashtable 中,每个元素都通过哈希函数映射到不同的位置,这样在读写元素时可以更快地定位到目标位置

结论:

  1. 哈希中的元素个数比较少,使用 ziplist 表示,元素个数比较多,使用 hashtable 来表示
  2. 每个 value 的值长度都比较短,使用 ziplist 表示,如果某个 value 的长度太长了,也会转换成 hashtable

  • hash-max-ziplist-entries 配置 (默认 512 个)​​​​​​​
  • hash-max-ziplist-value 配置(默认 64 字节)

理解:

  • 这两个配置项是均可以写到 redis.conf 文件中
  • 且两个配置的阈值是可变的,所以不用刻意的去 记背数值
  • 因此我们需在不同的业务场景中,通过测试等相关的手段,来调整上述配置的阈值,以便找到一个更加合适的数值

Hash 实际应用

Cache 缓存

  • 首先 String 类型是可以用作缓存的
  • 但对于 存储结构化的数据,即类似于数据库 表 这样的结构使用 hash 类型更适合一些

实例理解

  • Redis 存储结构化的数据

方式一:

  • 使用 hash 类型

注意:

  • 此处的 key 中已经包含了 uid,那 hash 中 value 存储的 uid 是不是有点多此一举?
  • 省去 hash 中 value 存储的 uid 是不是又可进一步节省存储空间?
  • 首先如果确实不想在 hash 中 value 存储 uid 也可以省略掉
  • 但是在工程实践中,通常会选择在哈希表的值 value 中再存储一份 uid
  • 因为这样有助于简化代码逻辑,并使代码在后续开发中更为方便使用

方式二:

  • 使用 string 类型 +  JSON 格式
set user:1 {"name": "mastermao", "age": 18, "city": "Changsha"}

注意:

  • 使用 string 类型 +  JSON 格式来表示 userinfo 时
  • 只想获取或修改其中的某个字段,就需要将整个 JSON 字符串读取出来
  • 再解析成对象,进行字段操作,然后再将其转换回 JSON 字符串,并写回 Redis 
  • 这样一系列过程相对繁琐

  • 相较之下使用 hash 的方式来表示 userinfo 
  • 可以使用字段 field 来表示对象的每个属性,类似于数据库 表 中的每个列
  • 这样可以更方便地修改或获取任何一个属性的值
  • 虽然 hash 的方式在读写字段 field 上更为直观、高效,但付出的代价是更大的存储空间需求
  • 此外需要控制 哈希表 在 ziplist 和 hashtable 两种内部编码的转换,可能会导致较大的内存消耗

  • 相比之下,使用 string 类型 +  JSON 格式的的内存消耗相对较小

方式三:

  • 原生 String 类型,一个属性对应一个键
  • 该方式相当于将同一个对象的各个属性 给分散开表示(低内聚)
set user:1:name mastermao
set user:1:age 18
set user:1:city Changsha
  • ​​​​​​​​​​​​​​​​​​​​​不建议使用该方式,该方式具有 低内聚性

理解高内聚低耦合

  • 内聚就是将有关联的东西放到一起,最好能放到指定的地方,其优点为 好找
  • 耦合就是两个模块 或 代码之间的关联关系,关联关系越大,越容易相互影响,则耦合也越大
  • 我们追求低耦合,避免 "牵一发而动全身",这边出一个 bug 同时也影响到了其他的地方

hash 类型 和 关系型数据库 的不同

  1. 哈希类型是稀疏的,而关系型数据库是完全结构化的
  2. ​​​​​​​关系型数据库 可以做到复杂的查询,而 Redis 去模拟关系型复杂查询,例如联表查询、聚合查询等 基本不可能,维护成本高

实例理解

  • 此处 哈希类型 每个键均有不同的字段 field
  • 但关系型数据库 一旦添加新的列,其所有的行需为该列设置一个值,即便为 null​​​​​​​

  • 这就是为什么哈希类型是稀疏的,而关系型数据库是完全结构化的原因

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++高阶(九)】C++类型转换以及IO流

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C   🔝🔝 C高阶 1. 前言2. C语言类型转换的方式3. C的强制…

5G阅信在教研行业应用场景有哪些?

1、新生入学 新生录用通知、录用信息查看、注意事项(入学指引) 校园简介 资讯1 秒速达,让信息传达更高效便捷 2、校务服务 可作为校园微服务的新入口 提供学校各专业课表课程查看、校园卡办理、一卡通应…

怎样在win10命令行窗口跑起来mujava

MuJava简介 Java (muJava) 是 Java 程序的变异系统。 它自动生成用于传统突变测试和类级别突变测试的突变体。 Java 可以测试单个类和多个类的包。 用户以对封装在单独 JUnit 类的方法中的被测类的方法调用序列的形式提供测试。 官网地址:Java Home Page 需要下…

正则表达式与bs4选择器筛选论文数准确率之比较

一、正则爬取论文网首页论文标题的示例 import requests import re from bs4 import BeautifulSoupheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36}def get_html(url):try:res…

C# 通过SharpCompress.Archives.Rar解压RaR文件

/// <summary>/// 解压一个Rar文件/// </summary>/// <param name"RarFile">需要解压的Rar文件&#xff08;绝对路径&#xff09;</param>/// <param name"TargetDirectory">解压到的目录</param>/// <param name&…

如何将图片(matlab、python)无损放入word论文

许多论文对插图有要求&#xff0c;直接插入png、jpg一般是不行的&#xff0c;这是一篇顶刊文章&#xff08;pdf&#xff09;的插图&#xff0c;放大2400%后依旧清晰&#xff0c;搜罗了网上的方法&#xff0c;总结了一下如何将图片无损放入论文中。 这里主要讨论的是数据生成的图…

渗透测试(Lab4.2)

配置WebDeveloper的时候遇到一个错误 导入失败&#xff0c;因为 E:…ovf 未通过 OVF 规范一致性或虚拟硬件合规性检查。 请单击“重试”放松 OVF 规范与虚拟硬件合规性检查&#xff0c;并重新尝试导入&#xff1b; 或单击“取消”以取消导入。如果重新尝试导入&#xff0c;可能…

[Angular] 笔记 10:服务与依赖注入

什么是 Services & Dependency Injection? chatgpt 回答&#xff1a; 在 Angular 中&#xff0c;Services 是用来提供特定功能或执行特定任务的可重用代码块。它们可以用于处理数据、执行 HTTP 请求、管理应用程序状态等。Dependency Injection&#xff08;依赖注入&#…

w16php系列之基础数组

一、索引数组 概念 索引数组 是指键名为整数的数组。默认情况下&#xff0c;索引数组的键名是从0开始&#xff0c;并依次递增。它主要适用于利用位置&#xff08;0、1、2……&#xff09;来标识数组元素的情况。另外&#xff0c;索引数组的键名也可以自己指定 示例代码 <…

VScode跑通Remix.js官方的contact程序开发过程

目录 1 引言 2 安装并跑起来 3 设置根路由 4 用links来添加风格资源 ​5 联系人路由的UI 6 添加联系人的UI组件 7 嵌套路由和出口 8 类型推理 9 Loader里的URL参数 10 验证参数并抛出响应 书接上回&#xff0c;我们已经跑通了remix的quick start项目&#xff0c;接下…

开源verilog模拟 iverilog verilator +gtkwave仿真及一点区别

开源的 iverilog verilator 和商业软件动不动几G几十G相比&#xff0c;体积小的几乎可以忽略不计。 两个都比较好用&#xff0c;各有优势。 iverilog兼容性好。 verilator速度快。 配上gtkwave 看波形&#xff0c;仿真工具基本就齐了。 说下基本用法 计数器 counter.v module…

HarmonyOS4.0开发该怎么系统学习,适合哪些人?

对于想要系统学习HarmonyOS 4.0开发的人来说&#xff0c;以下是一些建议&#xff1a; 1.了解HarmonyOS基础&#xff1a; 首先&#xff0c;你需要对HarmonyOS有一个基本的了解&#xff0c;包括它的核心概念、系统架构、分布式技术等。可以通过官方文档、教程和在线课程来深入了…

学习笔记15——前端和http协议

学习笔记系列开头惯例发布一些寻亲消息&#xff0c;感谢关注&#xff01; 链接&#xff1a;https://baobeihuijia.com/bbhj/ 关系 客户端&#xff1a;对连接访问到的前端代码进行解析和渲染&#xff0c;就是浏览器的内核服务器端&#xff1a;按照规则编写前端界面代码 解析标准…

园艺伴侣应用程序Plant-it

什么是 Plant-it &#xff1f; Plant-it 是一款园艺伴侣应用程序&#xff0c;可帮助您照顾植物。它不会建议您采取哪些操作&#xff0c;而是旨在记录您正在执行的活动。这是故意的&#xff0c;软件作者坚信&#xff0c;唯一负责知道何时给植物浇水、何时施肥等的人是你&#xf…

HBase深度历险 | 京东物流技术团队

简介 HBase 的全称是 Hadoop Database&#xff0c;是一个分布式的&#xff0c;可扩展&#xff0c;面向列簇的数据库&#xff0c;是一个通过大量廉价的机器解决海量数据的高速存储和读取的分布式数据库解决方案。本文会像剥洋葱一样&#xff0c;层层剥开她的心。 特点 首先我…

GaN HEMT的大信号(RF PA)性能

来源&#xff1a;Novel Drain-Connected Field Plate GaN HEMT Designs for Improved VBD −RON Tradeoff and RF PA Performance (IEEE TRANSACTIONS ON ELECTRON DEVICES) 使用 TCAD 提取的 I-V 和 C-V 曲线族&#xff0c;结合 Keysight 的 IC-CAP 器件建模套件和先进SPICE模…

工具系列:TimeGPT_(2)使用外生变量时间序列预测

文章目录 TimeGPT使用外生变量时间序列预测导入相关工具包预测欧美国家次日电力价格案例 TimeGPT使用外生变量时间序列预测 外生变量在时间序列预测中非常重要&#xff0c;因为它们提供了可能影响预测的额外信息。这些变量可以包括假日标记、营销支出、天气数据或与你正在预测…

JavaSE语法之十:抽象类(超全!!!)

文章目录 一、抽象类的概念二、抽象类的语法三、抽象类的特征四、抽象类的作用 一、抽象类的概念 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的。 如果一个类没有包含足够的信息来描绘一个…

Postman接口测试(附教程)

前言 之前还没实际做过接口测试的时候呢&#xff0c;对接口测试这个概念比较渺茫&#xff0c;只能靠百度&#xff0c;查看各种接口实例&#xff0c;然后在工作中也没用上&#xff0c;现在呢是各种各样的接口都丢过来…

1. pytorch mnist 手写数字识别

文章目录 一、数据集介绍1.1、简介1.2 详细介绍1、数据量2、标注量3. 标注类别4.数据下载5.数据集解读 二、读取、加载数据集1、pytorch 自带库函数2、通过重构Dataset类读取特定的MNIST数据或者制作自己的MNIST数据集 三、模型构建四、 runtraintest评估模型的性能检查点的持续…