【Redis】深入探索 Redis 的数据类型 —— 哈希表 hash
文章目录
- 前言
- 一、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
HSET
-
作用 : 指定的哈希表中设置字段的值,如果字段存在则更新,否则创建。并且可以同时设置多组字段。
-
语法:
HSET key field value [field value ... ]
HSETNX
- 作用:仅在字段不存在时,在指定的哈希表中设置字段的值。设置成功返回 1,否则返回 0。
- 语法:
HSETNX key field value
- 使用示例

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

当然,我会继续完善下面的部分,以涵盖哈希类型相关命令的详细说明:
1.3 HKEYS、HVALS 和 HGETALL
HKEYS
- 作用:获取指定哈希表中所有字段的名称。
- 语法:
HKEYS key
HVALS
- 作用:获取指定哈希表中所有字段的值。
- 语法:
HVALS key
HGETALL
- 作用:获取指定哈希表中所有字段和对应的值。
- 语法:
HGETALL key
- 使用案例

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

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

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

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的优势,提高数据访问的效率,同时保持灵活性和可维性。
相关文章:
【Redis】深入探索 Redis 的数据类型 —— 哈希表 hash
文章目录 前言一、hash 类型相关命令1.1 HSET 和 HSETNX1.2 HGET 和 HMGET1.3 HKEYS、HVALS 和 HGETALL1.4 HEXISTS 和 HDEL1.5 HLEN1.6 HINCRBY 和 HINCRBYFLOAT1.7 哈希相关命令总结 二、hash 类型内部编码三、hash 类型的应用场景四、原生,序列化,哈希…...
网络安全应急响应典型案例-(DDOS类、僵尸网络类、数据泄露类)
一、DDOS类事件典型案例 DDOS攻击,即分布式拒绝服务攻击,其目的在于使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致其正常用户无法访问。CC攻击使用代理服务器向受害服务器发送大量貌似合法的请求(通常…...
【测试开发】Mq消息重复如何测试?
本篇文章主要讲述重复消费的原因,以及如何去测试这个场景,最后也会告诉大家,目前互联网项目关于如何避免重复消费的解决方案。 Mq为什么会有重复消费的问题? Mq 常见的缺点之一就是消息重复消费问题,产生这种问题的原因是什么呢…...
C++和C#程序语言的区别
一直学习C++和C#,两者之间的区别总结一下 目录 一、两种语言概述 C++语言 C#语言 二、两种语言对比 2.1运行依赖...
CentOS配置Java环境报错-bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件
CentOS配置Java环境后执行java -version时报错: -bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件原因是所使用的jdk的版本和Linux内核架构匹配不上 使用以下命令查看Linux架构: [rootlocalhost ~]# cat /proc/version Linux version 3.1…...
MySQL进阶 —— 超详细操作演示!!!(上)
MySQL进阶 —— 超详细操作演示!!!(上) 一、存储引擎1.1 MySQL 体系结构1.2 存储引擎介绍1.3 存储引擎特点1.4 存储引擎选择 二、索引2.1 索引概述2.2 索引结构2.3 索引分类2.4 索引语法2.5 SQL 性能分析2.6 索引使用2…...
一条爬虫抓取一个小网站所有数据
一条爬虫抓取一个小网站所有数据 今天闲来无事,写一个爬虫来玩玩。在网上冲浪的时候发现了一个搞笑的段子网,发现里面的内容还是比较有意思的,于是心血来潮,就想着能不能写一个Python程序,抓取几条数据下来看看&am…...
八大排序——快速排序
Hello,大家好,今天分享的八大排序里的快速排序,所谓快速排序是一个叫霍尔的人发明,有很多人可能会觉得为什么不叫霍尔排序,其中原因就是因为它快,快速则体现了它的特点,今天我们就来讲一下快速排…...
【ES】笔记-Class类剖析
Class Class介绍与初体验ES5 通过构造函数实例化对象ES6 通过Class中的constructor实列化对象 Class 静态成员实例对象与函数对象的属性不相通实例对象与函数对象原型上的属性是相通的Class中对于static 标注的对象和方法不属于实列对象,属于类。 ES5构造函数继承Cl…...
数学建模--Seaborn库绘图基础的Python实现
目录 1.绘图数据导入 2. sns.scatterplot绘制散点图 3.sns.barplot绘制条形图 4.sns.lineplot绘制线性图 5.sns.heatmap绘制热力图 6.sns.distplot绘制直方图 7.sns.pairplot绘制散图 8.sns.catplot绘制直方图 9.sns.countplot绘制直方图 10.sns.lmplot绘回归图 1.绘图数…...
lv3 嵌入式开发-2 linux软件包管理
目录 1 软件包管理 1.1流行的软件包管理机制 1.2软件包的类型 1.3软件包的命名 2 在线软件包管理 2.1APT工作原理 2.2更新软件源 2.3APT相关命令 3 离线软件包管理 1 软件包管理 1.1流行的软件包管理机制 Debian Linux首先提出“软件包”的管理机制---Deb软件包 …...
智能小区与无线网络技术
1.1 智能小区 智能小区指的是具有小区智能化系统的小区。所谓小区智能化系统,指的是在 现代计算机网络和通信技术的基础上,将传统的土木建筑技术与计算机技术、自动 控制技术、通信与信息处理技术、多媒体技术等先进技术相结合的自动化和综…...
如何传输文件流给前端
通过链接下载图片,直接http请求然后将文件流返回 注:music.ly是一个下载tiktok视频的免费接口 https://api19-core-c-useast1a.musical.ly/aweme/v1/feed/?aweme_idxxx func (m *FileBiz) DownloadFileV2(ctx *ctrl.Context, fileLink, fileName strin…...
Spring Security OAuth2 远程命令执行漏洞
文章目录 一、搭建环境二、漏洞验证三、准备payload四、执行payload五、变形payload 一、搭建环境 cd vulhub/spring/CVE-2016-4977/ docker-compose up -d 二、漏洞验证 访问 http://192.168.10.171:8080/oauth/authorize?response_type${233*233}&client_idacme&s…...
Python之并发编程介绍
一、并发编程介绍 1.1、串行、并行与并发的区别 串行(serial):一个CPU上,按顺序完成多个任务并行(parallelism):指的是任务数小于等于cpu核数,即任务真的是一起执行的并发(concurrency):一个CPU采用时间片管理方式&am…...
GO语言网络编程(并发编程)并发介绍,Goroutine
GO语言网络编程(并发编程)并发介绍,Goroutine 1、并发介绍 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。 B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更…...
英语连词总结
前言 总结一些常用的英语连词,以下用法只是我希望我自己这么用。分类我可能分的不好,慢慢积累,慢慢改进。 1)表递进: firstly、secondly、thirdly、finally、af first、at the beginning、in the end、to begin with࿰…...
LeetCode 92. Reverse Linked List II【链表,头插法】中等
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
【图论】Floyd
算法提高课笔记) 文章目录 例题牛的旅行题意思路代码 排序题意思路代码 观光之旅题意思路代码 例题 牛的旅行 原题链接 农民John的农场里有很多牧区,有的路径连接一些特定的牧区。 一片所有连通的牧区称为一个牧场。 但是就目前而言,你…...
SpringCloudAlibaba Gateway(三)-整合Sentinel功能路由维度、API维度进行流控
Gateway整合Sentinel 前面使用过Sentinel组件对服务提供者、服务消费者进行流控、限流等操作。除此之外,Sentinel还支持对Gateway、Zuul等主流网关进行限流。 自sentinel1.6.0版开始,Sentinel提供了Gateway的适配模块,能针对路由(rou…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...
