本文是深入理解 Redis 常用数据类型源码及底层实现系列的第4篇~前3篇可移步( ̄∇ ̄)/
【Redis】深入理解 Redis 常用数据类型源码及底层实现(1.结构与源码概述)-CSDN博客
【Redis】深入理解 Redis 常用数据类型源码及底层实现(2.版本区别+dictEntry & redisObject详解)-CSDN博客
【Redis】深入理解 Redis 常用数据类型源码及底层实现(3.详解String数据结构)-CSDN博客
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会更节省内存空间)。