redis中hash数据结构及说明
golang学习网今天将给大家带来《redis中hash数据结构及说明》,感兴趣的朋友请继续看下去吧!以下内容将会涉及到数据结构、redisHash等等知识点,如果你是正在学习数据库或者已经是大佬级别了,都非常欢迎也希望大家都能给我建议评论哈~希望能帮助到大家!
hash的数据结构
- hash底层数据结构的实现包括两种:ziplist和字典当
- 保存的所有键值对字符串长度小于 64 字节并且键值对数量小于 512 时使用ziplist ,否则使用字典的方式
ziplist底层实现
ziplist是为了提高存储效率而设计的一种特殊编码的双向链表。它可以存储字符串或者整数,存储整数时是采用整数的二进制而不是字符串形式存储。
他能在O(1)的时间复杂度下完成list两端的push和pop操作。
但是因为每次修改操作都需要重新分配ziplist的内存,所以实际复杂度和ziplist的内存使用量相关
ziplist 中包含有zlbytes、zltail、zllen、entry、zlend等属性
zlbytes
:表示整个ziplist所占的空间大小,占4个字节zltail
:压缩列表尾元素相对于压缩列表起始地址的偏移量,占4个字节zllen
:压缩列表的元素数目,占两个字节;那么当压缩列表的元素数目超过(2^16)-1怎么处理呢?此时通过zllen字段无法获得压缩列表的元素数目,必须遍历整个压缩列表才能获取到元素数目zlend
:压缩列表的结尾,占一个字节,恒为0xFF(255)entry
:压缩列表存储的元素,可以为字节数组或者整数
entry 中包含有previous_entry_length、encoding、content等属性
previous_entry_length
:记录前一个节点的长度
该属性根据前一个节点的大小不同可以是1个字节或者5个字节;如果数值小于254,那就只用一个字节来表示长度,如果长度大于等于254就用5个字节,第一个字节是固定值254(FE)来标识这是个特殊的数据,剩下的4个字节来表示实际的长度
为什么要这么设计?
压缩列表目的是为了尽可能的节省存储空间,数据进行紧邻存储在一块连续的内存区域中;压缩表中元素的长度的是不同的,且为了减少存储空间,并没有保存前后节点的指针,无法通过后退指针来找到上一个元素,而通过保存上一个节点的长度,用当前的地址减去这个长度,就可以很容易的获取到了上一个节点的位置,通过一个一个节点向前回溯,来达到从表尾往表头遍历的操作
encoding
:数据的编码形式(字符串还是数字,长度是多少)content
:实际存储的数据
修改操作耗费性能:ziplist在内存中是高度紧凑的连续存储,这意味着它对修改并不友好,如果要对ziplist做修改类的操作,那就需重新分配新的内存来存储新的ziplist,代价很大
ziplist其实是一个逻辑上的双向链表,可以快速找到头节点和尾节点,然后每个节点(entry)中也包含指向前/后节点的"指针",但作者为了将内存节省到极致,摒弃了传统的链表设计(前后指针需要16字节的空间,而且会导致内存碎片化严重),设计出了内存非常紧凑的存储格式。
内存是省下来了,但操作复杂性也更新的复杂度上来了
字典
底层实现
字典(dict):其中包含长度为2的哈希表数组dictht,rehashIdx(默认-1)如果为-1说明当前没有扩容,如果不为 -1 则表示正在进行扩容,记录了原hash表需rehash的数组下标
hash表数组中,ht[0] 在第一次往字典中添加键值时分配内存空间,而另一个 ht[1] 将会在hash表中数组扩容/缩容才会进行空间分配
hash表(dictht)
:字典dictht数组元素,其中包括了
1 数据 dictEntry 类型的数组,每个数组的 item 可能都指向一个链表
2 数组长度 size
3 sizemask 等于 size - 1
4 当前 dictEntry 数组中包含总共多少节点
hash表数组中元素(dictEntry
):真正的数据节点,包括 key、value 和 next 节点
整体结构如下所示:
扩容
扩容时机:在dict->rehashidx == -1 , 也就是字典没有正在进行扩容/缩容的前提下,以下三种情况下对哈希表进行扩容并标记 dict->rehashidx 字段为0,且扩展的哈希表的数组大小是第一个hash表长度的 2倍
- 字典已使用节点数和数组大小之间的比率至少为 1:1,并且 dict_can_resize 为true
- 已使用节点数和字典大小之间的比率超过 dict_force_resize_ratio,该值默认为5
- 哈希表刚初始化完,是个空表,给哈希数组设置默认大小 DICT_HT_INITIAL_SIZE (4)
扩容方式:为ht[1]分配长度为ht[0]2倍长度,rehashIdx设置为0表示正在进行扩容rehash,采取渐进式rehash
redis对一个字典的rehash操作,不是一次性把该字典 dict->ht[0] 哈希表上所有哈希数组里的哈希数组元素全部重新哈希到 dict->ht[1]
而是将全部的rehash操作分散到对该字典操作的各个命令上了,每次进行"一步"哈希操作(增加k/v,删除k/v,查找key,随机返回key)
- 下标从dict->rehashidx开始,在 dict->ht[0].table 数组中找到第一个不为NULL的项
- 将该项链表上的所有元素全部hash映射到 ditct->ht[1] 上
- 每重新映射一个元素, dict->ht[0].used --, dict->ht[1].used ++
- 该项链表处理完后,将 dict->rehashidx ++
如果 dict->ht[0].used == 0,说明 dict->ht[0]中的元素已全部rehash到dict->ht[1],释放dict->ht[0].table 数组,设置 dict->ht[0] = dict->ht[1],重置 dict->ht[1]的字段,设置 dict->rehashidx = -1,rehash操作结束
缩容
字典有扩容也有缩容,从字典中删除key后,若字典中的元素个数与字典数组大小满足一定关系,会触发缩容操作,缩绒条件是:
哈希数组长度大于默认值DICT_HT_INITIAL_SIZE (4),且节点数量 与 字典哈希表数字大小的比例 小于10%
缩容后新数组长度为hash表中元素个数
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持golang学习网。
今天带大家了解了数据结构、redisHash的相关知识,希望对你有所帮助;关于数据库的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

- 上一篇
- RedisTemplate访问Redis的更好方法

- 下一篇
- Redis设置key的过期时间
-
- 悦耳的毛巾
- 太给力了,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢博主分享技术文章!
- 2023-05-03 00:21:00
-
- 落后的帆布鞋
- 太详细了,码起来,感谢up主的这篇文章,我会继续支持!
- 2023-04-10 17:56:35
-
- 会撒娇的月光
- 这篇博文真及时,很详细,感谢大佬分享,收藏了,关注大佬了!希望大佬能多写数据库相关的文章。
- 2023-03-28 17:32:26
-
- 老实的汉堡
- 这篇博文真是及时雨啊,作者加油!
- 2023-03-16 15:36:33
-
- 大方的火龙果
- 这篇文章内容真及时,好细啊,感谢大佬分享,已收藏,关注作者了!希望作者能多写数据库相关的文章。
- 2023-03-04 18:00:46
-
- 数据库 · Redis | 8小时前 |
- RedisSentinel高可用配置详解
- 468浏览 收藏
-
- 数据库 · Redis | 19小时前 |
- Redis配置加密技巧分享
- 268浏览 收藏
-
- 数据库 · Redis | 4天前 |
- Redis性能优化配置指南
- 182浏览 收藏
-
- 数据库 · Redis | 5天前 |
- RedisHyperLogLog大数据统计技巧
- 305浏览 收藏
-
- 数据库 · Redis | 6天前 |
- Redis安全配置参数设置详解
- 252浏览 收藏
-
- 数据库 · Redis | 6天前 |
- 不同环境Redis安全配置对比与调整方法
- 374浏览 收藏
-
- 数据库 · Redis | 1星期前 |
- RedisList队列优化方法分享
- 311浏览 收藏
-
- 数据库 · Redis | 1星期前 |
- Redis主从复制故障排查指南
- 178浏览 收藏
-
- 数据库 · Redis | 1星期前 |
- Redis原子操作详解与实战应用
- 469浏览 收藏
-
- 数据库 · Redis | 1星期前 |
- Redis崩溃后重启与数据恢复方法
- 153浏览 收藏
-
- 数据库 · Redis | 1星期前 |
- Redis安全配置:强密码与访问控制设置教程
- 440浏览 收藏
-
- 数据库 · Redis | 1星期前 |
- Redis单节点迁移集群的实用方法
- 376浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 514次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 499次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- AI Mermaid流程图
- SEO AI Mermaid 流程图工具:基于 Mermaid 语法,AI 辅助,自然语言生成流程图,提升可视化创作效率,适用于开发者、产品经理、教育工作者。
- 649次使用
-
- 搜获客【笔记生成器】
- 搜获客笔记生成器,国内首个聚焦小红书医美垂类的AI文案工具。1500万爆款文案库,行业专属算法,助您高效创作合规、引流的医美笔记,提升运营效率,引爆小红书流量!
- 659次使用
-
- iTerms
- iTerms是一款专业的一站式法律AI工作台,提供AI合同审查、AI合同起草及AI法律问答服务。通过智能问答、深度思考与联网检索,助您高效检索法律法规与司法判例,告别传统模板,实现合同一键起草与在线编辑,大幅提升法律事务处理效率。
- 678次使用
-
- TokenPony
- TokenPony是讯盟科技旗下的AI大模型聚合API平台。通过统一接口接入DeepSeek、Kimi、Qwen等主流模型,支持1024K超长上下文,实现零配置、免部署、极速响应与高性价比的AI应用开发,助力专业用户轻松构建智能服务。
- 746次使用
-
- 迅捷AIPPT
- 迅捷AIPPT是一款高效AI智能PPT生成软件,一键智能生成精美演示文稿。内置海量专业模板、多样风格,支持自定义大纲,助您轻松制作高质量PPT,大幅节省时间。
- 637次使用
-
- Golang迭代如何在Go中循环数据结构使用详解
- 2022-12-22 148浏览
-
- 详解如何在Go语言中循环数据结构
- 2022-12-22 406浏览
-
- Go语言数据结构之双链表学习教程
- 2022-12-30 280浏览
-
- Go语言数据结构之希尔排序示例详解
- 2022-12-23 185浏览
-
- Go数据结构之堆排序示例详解
- 2022-12-28 183浏览