【Redis】深入探索 Redis 的数据类型 —— 哈希表 hash

news2024/11/24 11:09:47

文章目录

  • 前言
  • 一、hash 类型相关命令
    • 1.1 HSET 和 HSETNX
    • 1.2 HGET 和 HMGET
    • 1.3 HKEYS、HVALS 和 HGETALL
    • 1.4 HEXISTS 和 HDEL
    • 1.5 HLEN
    • 1.6 HINCRBY 和 HINCRBYFLOAT
    • 1.7 哈希相关命令总结
  • 二、hash 类型内部编码
  • 三、hash 类型的应用场景
  • 四、原生,序列化,哈希类型缓存方式对比
    • 4.1 原生字符串类型
    • 4.2 序列化字符串类型(例如JSON格式)
    • 4.3 哈希类型
    • 4.4 总结


前言

在构建和优化应用程序时,数据缓存是提高性能和降低数据库负载的关键策略之一。Redis(Remote Dictionary Server)是一个高性能的内存数据库,广泛用于数据缓存和快速数据访问。其中,哈希类型(Hash)是 Redis 中的一种强大数据结构,通常用于存储对象、映射关系和键值对等数据。

在本文中,我们将深入探讨Redis中的哈希类型。我们将从哈希类型的基本命令入手,逐步介绍它们的使用方法、内部编码方式以及在实际应用场景中的应用。通过学习和理解 Redis 哈希类型,可以帮助我们够更好地利用 Redis 来优化数据存储和访问,提高应用程序的性能。

接下来,让我们深入了解 Redis 哈希类型的相关内容。

一、hash 类型相关命令

1.1 HSET 和 HSETNX

  1. HSET
  • 作用 : 指定的哈希表中设置字段的值,如果字段存在则更新,否则创建。并且可以同时设置多组字段。

  • 语法:

    HSET key field value [field value ... ]
    
  1. HSETNX
  • 作用:仅在字段不存在时,在指定的哈希表中设置字段的值。设置成功返回 1,否则返回 0。
  • 语法:
    HSETNX key field value 
    
  1. 使用示例

1.2 HGET 和 HMGET

  1. HGET
  • 作用:获取指定哈希表中字段的值。
  • 语法:
    HGET key field
    
  1. HMGET
  • 作用:是获取指定哈希表中多个字段的值。
  • 语法:
    HMGET key field1 [field2 ...]
    
  1. 使用示例

当然,我会继续完善下面的部分,以涵盖哈希类型相关命令的详细说明:

1.3 HKEYS、HVALS 和 HGETALL

  1. HKEYS
  • 作用:获取指定哈希表中所有字段的名称。
  • 语法
    HKEYS key
    
  1. HVALS
  • 作用:获取指定哈希表中所有字段的值。
  • 语法
    HVALS key
    
  1. HGETALL
  • 作用:获取指定哈希表中所有字段和对应的值。
  • 语法
    HGETALL key
    
  1. 使用案例

1.4 HEXISTS 和 HDEL

  1. HEXISTS
  • 作用:检查指定哈希表中是否存在某个字段。
  • 语法
    HEXISTS key field
    
  1. HDEL
  • 作用:删除指定哈希表中的一个或多个字段。
  • 语法
    HDEL key field1 [field2 ...]
    
  1. 使用案例

1.5 HLEN

  1. HLEN
  • 作用:获取指定哈希表中字段的数量(即哈希表的大小)。
  • 语法
    HLEN key
    
  1. 使用案例

1.6 HINCRBY 和 HINCRBYFLOAT

  1. HINCRBY
  • 作用:将哈希表中指定字段的值增加一个整数。
  • 语法
    HINCRBY key field increment
    
  1. HINCRBYFLOAT
  • 作用:将哈希表中指定字段的值增加一个浮点数。
  • 语法
    HINCRBYFLOAT key field increment
    
  1. 使用案例

1.7 哈希相关命令总结

以下是哈希类型相关命令的总结,包括命令、作用和时间复杂度:

命令作用时间复杂度
HSET在哈希表中设置字段的值,存在则更新,否则创建。可同时设置多组字段。O(1)
HSETNX仅在字段不存在时,在哈希表中设置字段的值,成功返回1,否则返回0。O(1)
HGET获取指定哈希表中字段的值。O(1)
HMGET获取指定哈希表中多个字段的值。O(N),N为字段数
HKEYS获取指定哈希表中所有字段的名称。O(N),N为字段数
HVALS获取指定哈希表中所有字段的值。O(N),N为字段数
HGETALL获取指定哈希表中所有字段和对应的值。O(N),N为字段数
HEXISTS检查指定哈希表中是否存在某个字段。O(1)
HDEL删除指定哈希表中的一个或多个字段。O(N),N为被删除的字段数
HLEN获取指定哈希表中字段的数量(即哈希表的大小)。O(1)
HINCRBY将哈希表中指定字段的值增加一个整数。O(1)
HINCRBYFLOAT将哈希表中指定字段的值增加一个浮点数。O(1)

二、hash 类型内部编码

Redis 是一种高性能的内存数据库,支持多种数据结构,包括哈希(Hash)。在 Redis 中,哈希数据类型有两种内部编码方式,分别是 ziplist(压缩列表)和 hashtable(哈希表)。这两种编码方式的选择取决于哈希的大小和存储特性。

1. ziplist(压缩列表):

ziplist 是 Redis 中用于内部编码较小哈希的紧凑数据结构。以下是一些关于 ziplist 的关键特性:

  • 当哈希类型的元素个数相对较少,且所有字段和对应的值都满足一定的限制条件时,Redis 会使用 ziplist 作为哈希的内部实现。
  • 默认情况下,Redis 会选择 ziplist。具体来说,如果哈希的元素个数不超过 512 个,并且所有值都小于 64 字节,那么 ziplist 就是首选的编码方式。
  • Ziplist 是一种紧凑的数据结构,它能够在节省内存方面表现得比 hashtable 更出色。它将多个哈希元素连续存储在一起,有效地减少了内存占用。

2. hashtable(哈希表):

hashtable 是 Redis 中用于存储大规模哈希数据的内部编码方式。以下是 hashtable 的关键特性:

  • 当哈希类型的元素个数超过了 ziplist 的配置限制,或者有字段对应的值大于 64 字节时,Redis 会将内部编码切换为 hashtable。
  • Hashtable 是一种散列表数据结构,它具有 O(1) 的读写时间复杂度,适用于大规模的哈希数据集。
  • 切换到 hashtable 可以提供更好的性能和内存管理,特别是在处理大型哈希或包含大值的情况下。

根据上述描述,下面是一些示例演示哈希数据类型的内部编码以及在何种条件下会发生编码转换:

示例 1:使用 ziplist 编码

> hmset hashkey f1 v1 f2 v2
OK
> object encoding hashkey
"ziplist"

在此示例中,由于字段数较少且值满足条件,Redis 使用 ziplist 作为内部编码。

示例 2:切换到 hashtable 编码

> hset hashkey f3 "one string is bigger than 64 bytes ..." 1
OK
> object encoding hashkey
"hashtable"

在此示例中,因为有一个字段对应的值大于 64 字节,Redis 将内部编码切换为 hashtable。

示例 3:切换到 hashtable 编码

> hmset hashkey f1 v1 h2 v2 f3 v3 ... (超过 512 个字段) ...
OK
> object encoding hashkey
"hashtable"

在此示例中,由于字段数超过了 512 个,Redis 将内部编码转换为 hashtable。

这些内部编码方式的选择是为了在不同情况下平衡内存占用和性能。Redis 会根据需要自动进行这些编码转换,以优化存储和操作效率。无论您的哈希数据集大小如何,Redis 都会根据配置和数据特性智能地选择适当的内部编码方式。这种自动优化确保了 Redis 在各种工作负载下的出色性能表现。

三、hash 类型的应用场景

在本部分,我们将探讨哈希类型在应用程序中的实际应用场景。首先,让我们回顾一下关系型数据库中保存用户信息的结构。

关系型数据表保存用户信息

上图展示了关系型数据表记录的两条用户信息,其中用户的属性表现为表的列,每条用户信息则表现为行。如果我们想在 Redis 中映射这两个用户信息,可以使用哈希类型。

使用哈希类型映射用户信息:

映射关系表示用户信息

相比于使用 JSON 格式的字符串缓存用户信息,哈希类型更加直观,并且在更新操作上更加灵活。我们可以将每个用户的 ID 定义为键的后缀,然后使用多个 field-value 对应用户的各个属性,类似以下伪代码:

UserInfo getUserInfo(long uid) {
    // 根据 uid 得到 Redis 的键
    String key = "user:" + uid;

    // 尝试从 Redis 中获取对应的值
    userInfoMap = Redis 执行命令:hgetall key;

    // 如果缓存命中(hit)
    if (userInfoMap != null) {
        // 将映射关系还原为对象形式
        UserInfo userInfo = 利用映射关系构建对象(userInfoMap);
        return userInfo;
    }

    // 如果缓存未命中(miss)
    // 从数据库中,根据 uid 获取用户信息
    UserInfo userInfo = MySQL 执行 SQL:select * from user_info where uid = <uid>;

    // 如果表中没有 uid 对应的用户信息
    if (userInfo == null) {
        响应 404;
        return null;
    }

    // 将缓存以哈希类型保存
    Redis 执行命令:hmset key name userInfo.name age userInfo.age city userInfo.city;

    // 写入缓存,为了防止数据腐烂(rot),设置过期时间为 1 小时(3600 秒)
    Redis 执行命令:expire key 3600;

    // 返回用户信息
    return userInfo;
}

上述代码演示了一个常见的缓存策略,首先尝试从 Redis 缓存中获取数据,如果未命中则从数据库中检索,并将结果存储到 Redis 中以便后续访问。这种策略可以提高访问性能并减轻数据库负担。

然而,需要注意的是哈希类型和关系型数据库存在两个主要差异:

  • 哈希类型的稀疏性: 哈希类型允许每个键具有不同的 field,而关系型数据库在添加新的列时需要为所有行设置值,即使是 null。

  • 复杂关系查询的不适用性: 关系型数据库支持复杂的关系查询,而 Redis 不适用于模拟关系型复杂查询,例如联表查询和聚合查询,维护成本较高。

关系型数据库的稀疏性示例:

关系型数据库稀疏性

通过哈希类型,我们可以更直观地映射和存储用户信息,适应不同应用场景的需求。哈希类型的使用方式简单、直观、灵活,特别适合局部属性的变更和查询操作,同时也具有较好的内存效率。

四、原生,序列化,哈希类型缓存方式对比

当涉及到缓存用户信息时,有多种不同的缓存方式可供选择。以下是对三种常见的缓存方式进行详细比较和分析:原生字符串类型、序列化字符串类型(例如JSON格式),以及哈希类型。这里探讨它们的实现方法、优点和缺点,以帮助您更好地选择适用于您应用程序的缓存策略。

4.1 原生字符串类型

实现方法: 使用原生字符串类型,将每个用户属性存储为单独的键值对,例如:

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

优点:

  • 实现简单,每个属性都以单独的键存储,易于理解和维护。
  • 针对个别属性变更很灵活。

缺点:

  • 占用过多的键,导致内存占用量较大。
  • 用户信息在Redis中分散存储,缺少内聚性,不便于批量操作和管理。
  • 不适用于需要一次性获取完整用户信息的情况,需要大量的键操作。

适用场景: 这种方式适合于需要对用户属性进行个别、频繁变更的场景,但不适用于需要一次性获取完整用户信息的情况。

4.2 序列化字符串类型(例如JSON格式)

实现方法: 使用序列化字符串类型,将用户信息以JSON格式等方式序列化后存储为一个键值对,例如:

set user:1 {"name": "James", "age": 23, "city": "Beijing"}

优点:

  • 适用于以整体作为操作单元的信息存储,编程较为简单。
  • 可以高效地使用内存,特别适合存储大对象或数据结构。

缺点:

  • 序列化和反序列化需要一定开销。
  • 不适合频繁进行个别属性的更新或查询,缺乏灵活性。

适用场景: 这种方式适用于需要一次性获取完整用户信息的场景,特别是当用户信息是复杂对象或数据结构时。

4.3 哈希类型

实现方法: 使用哈希类型,将用户信息存储为Redis的哈希类型,例如:

hmset user:1 name James age 23 city Beijing

优点:

  • 简单、直观、灵活。
  • 适用于信息的局部变更或获取操作,支持对单个属性的读写。
  • 内部编码可以是 ziplist 或 hashtable,具有较好的灵活性和内存效率。

缺点:

  • 需要控制哈希在 ziplist 和 hashtable 两种内部编码之间的转换,可能会带来内存消耗。
  • 不适合需要一次性获取完整用户信息的情况,可能需要多次读取。

适用场景: 哈希类型适用于需要对用户属性进行局部变更或频繁单独属性操作的场景,也适合需要对属性进行灵活查询的情况。

4.4 总结

选择合适的缓存方式应根据具体的应用需求和访问模式来确定。通常情况下,可以根据不同的数据特点和操作需求,综合考虑这三种缓存方式,并在应用程序中进行适当的组合和使用,以获得最佳性能和灵活性。

例如,可以使用哈希类型缓存来处理局部属性的变更和查询,同时使用序列化字符串类型缓存来获取完整用户信息。这样,可以充分发挥Redis的优势,提高数据访问的效率,同时保持灵活性和可维性。

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

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

相关文章

怎样去掉win11快捷方式的小箭头

前有创造注册表新值的方法,现在有了注册表加文件的方法 开始 先下载这个文件,里面有要用到的信息 下载 保存文件到电脑,并解压 有两个文件, 一个是 Remove_shortcut_arrow_icon.reg 一个是blank.ico 把第二个文件移动到 C:\Windows 文件夹, 然后点击打开文件, 如果提示是…

Windows11下Python安装GTK4

在Python下使用GTK无法直接使用pip安装PyGObject库 打卡MSYS终端&#xff0c;依次执行&#xff1a; pacman -Suy pacman -S mingw-w64-x86_64-gtk4 mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-pip mingw-w64-x86_64-python3-gobject mingw-w64-x86_64-libadwaita min…

Kotlin File writeText appendText appendBytes readBytes readText

Kotlin File writeText appendText appendBytes readBytes readText import java.io.Filefun main(args: Array<String>) {val filePath "./myfile.txt"val file File(filePath)file.writeText("hello,") //如果原有文件有内容&#xff0c;将完全覆…

八大排序——快速排序

Hello&#xff0c;大家好&#xff0c;今天分享的八大排序里的快速排序&#xff0c;所谓快速排序是一个叫霍尔的人发明&#xff0c;有很多人可能会觉得为什么不叫霍尔排序&#xff0c;其中原因就是因为它快&#xff0c;快速则体现了它的特点&#xff0c;今天我们就来讲一下快速排…

李宏毅-hw5-translation-有关transformer、seq2seq的探索

一、ppt研读&#xff1a; 1.关于这个 input Embedding 的内容: 2.关于Positional Encoding&#xff1a; 二、慢慢积累&#xff0c;一点点阅读代码&#xff1a; 虽然这次的模块挺多的&#xff0c;但是&#xff0c;这样也就意味着&#xff0c;把这个内化为自己的&#xff0c;就…

【面试经典150 | 数组】合并两个有序数组

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;合并排序方法二&#xff1a;双指针方法三&#xff1a;原地操作-从前往后方法四&#xff1a;原地操作-从后往前 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章…

Axure RP 9 for Mac/Windows图文安装教程

Axure RP 9是一款一款专业级快速产品原型设计工具&#xff0c;使用它可以让用户快速、高效创建应用软件或Web网站的线框图、流程图、原型和规格说明文档。 Axure RP 9 for Mac采用了极简主义的设计&#xff0c;界面布局更加清爽简洁&#xff0c;操作也非常简单&#xff0c;并且…

系统架构设计专业技能 ·操作系统

现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 点击进入系列文章目录 系统架构设计高级技能 操作系统 一、操作系统概述二、进程管理2.1 进程概念2.2 进…

VSCode中配置命令行参数

VSCode中配置命令行参数 在跑程序调试的时候&#xff0c;可以直接使用脚本运行程序&#xff0c;这个时候调试代码只能用pdb ,我觉得不太习惯&#xff0c;而且感觉不是很好&#xff0c;所以想这能不能将运行程序的脚本中的命令直接配置到vscode上&#xff0c;就有了这篇记录。 …

oCPC实践录 | oCPC转化的设计、选择、归因与成本设置(2)

在oCPC实践录 | oCPC转化的设计、选择、归因与成本设置&#xff08;1&#xff09;中初步介绍了平台侧和广告主侧的转化设计&#xff0c;这篇文章介绍平台侧和广告主怎么选择转化目标&#xff0c;归因与成本控制。 一 上周受公司增长部门的同事邀请做了一场分享和交流&#xf…

Cesium 制作风流场,制作风场可视化

需求 Cesium 制作风场 预览 分析 以下是开发中参考的几个博主的案例 博客一&#xff1a;风场热力图博客二博客三 风场数据准备&#xff0c;data.json 由于数据量过大&#xff0c;我这边只做格式展示&#xff0c;想要完整 json 文件&#xff0c;可以在我的资源里获取 […

A Yet Another Remainder The 2022 ICPC Asia Regionals Online Contest (II)

PTA | 程序设计类实验辅助教学平台 题目大意&#xff1a;有一个n位长的隐藏数x&#xff0c;从高位到低位依次标号为1到n&#xff0c;sum[i][j]表示从第i为开始每j位上的数的和&#xff0c;有q次询问&#xff0c;每次给出一个100以内除了5以外的质数p&#xff0c;问这个数%p等于…

免费版Photoshop2024智能人像磨皮插件

Portraiture是一款智能磨皮插件&#xff0c;为Photoshop和Lightroom添加一键磨皮美化功能&#xff0c;快速对照片中皮肤、头发、眉毛等部位进行美化&#xff0c;无需手动调整&#xff0c;大大提高P图效率。全新4版本&#xff0c;升级AI算法&#xff0c;并独家支持多人及全身模式…

企业架构LNMP学习笔记32

企业架构LB-服务器的负载均衡之LVS实现&#xff1a; 学习目标和内容 1&#xff09;能够了解LVS的工作方式&#xff1b; 2&#xff09;能够安装和配置LVS负载均衡&#xff1b; 3&#xff09;能够了解LVS-NAT的配置方式&#xff1b; 4&#xff09;能够了解LVS-DR的配置方式&…

基于SSM的生鲜电商系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

Linux高性能服务器编程 学习笔记 第一章 TCP/IP协议族

现在Internet使用的主流协议族是TCP/IP协议族&#xff0c;它是一个分层、多协议的通信体系。 TCP/IP协议族包含众多协议&#xff0c;我们只详细讨论IP协议和TCP协议&#xff0c;因为它们对编写网络应用程序有最直接的影响。如果想系统学习网络协议&#xff0c;RFC&#xff08;…

LeetCode147之对链表进行插入排序(相关话题:链表)

题目描述 给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列…

深度解析自然语言处理之篇章分析

在本文中&#xff0c;我们深入探讨了篇章分析的概念及其在自然语言处理&#xff08;NLP&#xff09;领域中的研究主题&#xff0c;以及两种先进的话语分割方法&#xff1a;基于词汇句法树的统计模型和基于BiLSTM-CRF的神经网络模型。 关注TechLead&#xff0c;分享AI全维度知识…

LLM推理优化技术综述:KVCache、PageAttention、FlashAttention、MQA、GQA

LLM推理优化技术综述&#xff1a;KVCache、PageAttention、FlashAttention、MQA、GQA 随着大模型被越来越多的应用到不同的领域&#xff0c;随之而来的问题是应用过程中的推理优化问题&#xff0c;针对LLM推理性能优化有一些新的方向&#xff0c;最近一直在学习和研究&#xf…

react-native实现 TextInput 键盘显示搜索按钮并触发回调

<TextInput returnKeyType"search"returnKeyLabel"搜索"onSubmitEditing{e > {toSearch(keyword);}} /><SearchBarref{serachBarEl}placeholder"请输入"onChangeText{handleChangeSearch}value{search}onSubmitEditing{handleSearch…