0
点赞
收藏
分享

微信扫一扫

redis中hash数据结构

滚过红尘说红尘 2022-05-04 阅读 65

目录

hash的数据结构

  • hash底层数据结构的实现包括两种:ziplist和字典
  • 当保存的所有键值对字符串长度小于 64 字节并且键值对数量小于 512 时使用ziplist ,否则使用字典的方式

ziplist底层实现

字典

底层实现
  • 字典(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:1,并且 dict_can_resize 为true
  2. 已使用节点数和字典大小之间的比率超过 dict_force_resize_ratio,该值默认为5
  3. 哈希表刚初始化完,是个空表,给哈希数组设置默认大小 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)
  1. 下标从dict->rehashidx开始,在 dict->ht[0].table 数组中找到第一个不为NULL的项
  2. 将该项链表上的所有元素全部hash映射到 ditct->ht[1] 上
  3. 每重新映射一个元素, dict->ht[0].used --, dict->ht[1].used ++
  4. 该项链表处理完后,将 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表中元素个数

引用

https://blog.csdn.net/a158372582/article/details/106234075
https://baijiahao.baidu.com/s?id=1686862206783599500&wfr=spider&for=pc

举报

相关推荐

0 条评论