Hash数据结构
看过前面的介绍,大家应该知道 Redis 的 Hash 结构的底层实现在 6 和 7 是不同的,Redis 6 是 ziplist 和 hashtable,Redis 7 是 listpack 和 hashtable。
我们先使用config get hash*看下 Redis 6 和 Redis 7 的 Hash 结构配置情况(在Redis客户端的命令行界面中使用INFO server可以查看包括版本号等各个信息)
通过Docker拉取一个Redis7的镜像,同样的命令查看相关信息
可以看到Redis7多了hash-max-listpack-entries和hash-max-listpack-value两项,我们先介绍下这四个参数的含义:
- hash-max-ziplist-entries:使用压缩列表保存数据时,哈希集合中最大的元素个数
- hash-max-ziplist-value:使用压缩列表保存数据时,哈希集合中单个元素的最大长度
-
- 单位byte:一个英文字母一个byte
- hash-max-listpack-entries:使用紧凑列表保存数据时,哈希集合中最大的元素个数
- hash-max-listpack-value:使用紧凑列表保存数据时,哈希集合中单个元素的最大长度
上面两张图中的参数都是默认情况,为了方便测试效果我们把这两个值都改小些(如下图)
依次存储不同长度的值,并查看编码方式
有上面两张图可以看到,当同时满足字段个数小于hash-max-ziplist-entries并且字段值都小于hash-max-ziplist-value时,才会使用OBJ_ENCODING_ZIPLIST的编码方式进行存储,二者不满足任意一个就会转换为OBJ_ENCODING_HT的编码方式进行存储,并且不可逆(OBJ_ENCODING_ZIPLIST变成OBJ_ENCODING_HT可以,但是即便存储的数据又满足了上面提到的两个要求,OBJ_ENCODING_HT也不会再变回OBJ_ENCODING_ZIPLIST(反反复复浪费性能),相比较OBJ_ENCODING_HT,OBJ_ENCODING_ZIPLIST会更节省内存空间)。
源码分析
t_hash.c
hashtable在Redis中被称为“字典”,他是一个数组+链表的结构
OBJ_ENCODING_HT这种编码方式内部才是真正的哈希表结构,或称为字典结构,有一个dictEntry,详见下图源代码:
OBJ_ENCODING_HT这种编码方式内部才是真正的哈希结构(或称为字典结构),其可以实现O(1)的时间复杂度的读写操作,因此效率很高,在Redis内部,从OBJ_ENCODING_HT类型到底层真正的散列表数据结构是一层一层嵌套起来的,组织关系如