您现在的位置是:亿华云 > 数据库
深入理解:Redis哈希结构内存模型剖析
亿华云2025-10-04 03:21:57【数据库】4人已围观
简介本文主要阐述 Redis中使用 最为频繁的数据类型:哈希或称散列),在Redis内部是怎么存的。 本文内容脑图如下:
本文主要阐述 Redis中使用 最为频繁的深入数据类型:哈希(或称散列),在Redis内部是理解怎么存的。
本文内容脑图如下:
哈希类型内部编码详情
对于 Redis的希结型剖析常用 5 种数据类型(String、Hash、构内List、存模Set、深入sorted set),理解每种数据类型都提供了 最少两种 内部的希结型剖析编码格式,而且每个数据类型内部编码方式的构内选择 对用户是完全透明的 ,Redis会根据数据量自适应地选择较优化的存模内部编码格式。
如果想查看某个键的深入内部编码格式,可以使用 OBJECT ENCODING keyname 指令来进行,理解比如:
127.0.0.1:6379> 127.0.0.1:6379> set foo bar OK127.0.0.1:6379> 127.0.0.1:6379> object encoding foo // 查看某个Redis键值的希结型剖析编码"embstr"127.0.0.1:6379> 127.0.0.1:6379>对于使用最为频繁的 Hash类型,其内部编码方式可能有两种:
OBJ_ENCODING_ZIPLIST (压缩列表)
OBJ_ENCODING_HT (哈希表)
Redis 会根据 数据量 的构内情况来 自适应 地选择这两种编码方式中 较优 的一种,而这一切对用户完全透明。存模
在 数据条目较少 , 数据值较小 的时候 Redis会采用 压缩列表 (OBJ_ENCODING_ZIPLIST)编码方式进行存储。这里成员"较少",成员值"较小"的云南idc服务商标准可以通过如下配置项进行配置:
hash-max-ziplist-entries 512hash-max-ziplist-value 64Redis 默认给出了默认值,当然用户可根据实际情况自行配置。
当 Hash类型键的字段个数 < hash-max-ziplist-entries 并且 每个字段名和字段值的长度 < hash-max-ziplist-value 时,Redis 会使用 OBJ_ENCODING_ZIPLIST来存储该键,反之则会转换为 OBJ_ENCODING_HT的编码方式。
口说无凭,我们不妨先来做个实验感受一下吧:
很明显该实验验证了当 字段值长度大于64 时,编码格式会由 ZIPLIST方式切换为 Hashtable方式。
源码之前,了无秘密,我们再来看一下Redis关于这部分切换的源码实现,那就理解得更加清楚了:
下面详解 OBJ_ENCODING_ZIPLIST 和 OBJ_ENCODING_HT 这两种编码格式的内部存储模型,知道了其各自特点和优缺点,自然也就明白了Redis内部使用它们的意图。
OBJ_ENCODING_ZIPLIST 编码
Ziplist 压缩列表是一种紧凑编码格式,总体思想是 时间换空间 ,即以部分读写性能为代价,来换取极高的内存空间利用率,因此只会用于 字段个数少 ,且 字段值也较小 的场景。 给大家推荐一个架构交流群: 698581634 进群即可免费获取资料 。
压缩列表内存利用率极高的原因与其连续内存的服务器托管特性是分不开的,其典型的内存结构可以用下图形象地展示出来:
所以如果用 Ziplist来存储 Redis的散列类型的话,元素的排列方式就变成了如下图所示的形象示意图:即key和value都是逻辑连续内存:
OBJ_ENCODING_HT 编码
OBJ_ENCODING_HT 这种编码方式内部才是真正的哈希表结构,或称为字典结构,其可以实现O(1)复杂度的读写操作,因此效率很高。
在 Redis内部,从 OBJ_ENCODING_HT类型到底层真正的散列表数据结构是一层层嵌套下去的,关系如下:
这一关系我们可以从 Redis哈希表定义部分的源码来看出:
下面来详解一下各个部分:
关于哈希节点(dictEntry)
关于哈希表(dictht)和字典(dict)
关于dictType
Redis如何计算Hash值
Redis计算Hash的源代码如下:
这是一个 C语言宏定义,其实幕后真正承担 Hash值计算的是上面介绍的 dictType结构体中的函数指针 hashFunction。 给大家推荐一个架构交流群: 698581634 进群即可免费获取资料 。
而该 hashFunction函数指针在初始化时会对应被赋值为一个个真实的服务器租用计算 Hash值的实际函数,就像下面这样:
Redis如何计算存取索引Index值
Index值的计算依赖于上面计算得出的 Hash值,代码如下:
到此,还有一个 一直非常值得关注的细节 :即字典 dict里总是保存有两个 Hash表结构 ht[2] ,以及与其高度相关的 rehash操作 ,这在下一篇文章里详解。
原文链接:https://my.oschina.net/hansonwang99/blog/1934354
由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!
很赞哦!(73)
相关文章
- 互联网其实拼的也是人脉,域名投资也是一个时效性很强的东西,一个不起眼的消息就会引起整个域名投资市场的动荡,因此拓宽自己的人脉圈,完善自己的信息获取渠道,让自己能够掌握更为多样化的信息,这样才更有助于自己的域名投资。
- 干货分享,如何查询域名是否被注册了呢?
- 硬核!15张图解Redis为什么这么快
- 忘记MySQL密码怎么办?一招教你搞定!
- 众所周知,com域名拥有最大的流通市场和流通历史。最好选择com域名,特别是在购买域名时处理域名。其次可以是cn域名、net域名、org域名等主流域名,现在比较流行的王域名和顶级域名,都是值得注册和投资的。
- MySQL事务与MVCC如何实现的隔离级别
- 5000多张数据表,如何用SQL迁移到数据仓库?
- 大家知道什么是域名吗?
- 第六:这个圈子里的域名确实是赚钱的一些大玩家,至于小米农,有多少赚钱?几乎没有,也就是说,轿子里只有一个人,而且大多数人都抬着轿子。
- 在鸿蒙系统上实现权限请求框架—桃夭权限请求框架