Redis入门到通关之数据结构解析-Dict



在这里插入图片描述

欢迎来到 请回答1024 的博客

🍓🍓🍓欢迎来到 请回答1024的博客

关于博主: 我是 请回答1024,一个追求数学与计算的边界、时间与空间的平衡,0与1的延伸的后端开发者。

博客特色: 在我的博客中,开设了如下专栏(点击可以进入专栏奥~): JavaMySQLRedisSpringSpringBootSpringCloudRabbitMQ微服务分布式 等相关技术专栏。期待与您一起,探索编程世界中的发现和创新之旅。

🍎🍎🍎我的主页 : https://reply1024.blog.csdn.net

敬请期待定期更新、见解和教程!让我们一起踏上这段编码冒险之旅!

数学与计算的边界 时间与空间的平衡 0与1的延伸


概述

我们知道Redis是一个键值型(Key-Value Pair)的数据库,我们可以根据键实现快速的增删改查。而键与值的映射关系正是通过Dict来实现的。

Dict由三部分组成,分别是:哈希表(DictHashTable)、哈希节点(DictEntry)、字典(Dict)

在这里插入图片描述

当我们向Dict添加键值对时,Redis首先根据key计算出hash值(h),然后利用 h & sizemask来计算元素应该存储到数组中的哪个索引位置。

我们存储k1=v1,假设k1的哈希值h =1,则1&3 =1,因此k1=v1要存储到数组角标1位置。

在这里插入图片描述

构成

Dict由三部分组成,分别是:哈希表(DictHashTable)、哈希节点(DictEntry)、字典(Dict)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


Dict的扩容

Dict 中的 HashTable 就是数组结合单向链表的实现,当集合中元素较多时,必然导致哈希冲突增多,链表过长,则查询效率会大大降低。

Dict在每次新增键值对时都会检查负载因子(LoadFactor = used/size) ,满足以下两种情况时会触发哈希表扩容:

  • 哈希表的 LoadFactor >= 1,并且服务器没有执行 BGSAVE 或者 BGREWRITEAOF 等后台进程;
  • 哈希表的 LoadFactor > 5 ;

在这里插入图片描述

在这里插入图片描述


Dict的rehash

不管是扩容还是收缩,必定会创建新的哈希表,导致哈希表的size和sizemask变化,而key的查询与sizemask有关。因此必须对哈希表中的每一个key重新计算索引,插入新的哈希表,这个过程称为rehash。过程是这样的:

  • 计算新hash表的realeSize,值取决于当前要做的是扩容还是收缩:

    • 如果是扩容,则新size为第一个大于等于dict.ht[0].used + 1的2^n
    • 如果是收缩,则新size为第一个大于等于dict.ht[0].used的2^n (不得小于4)
  • 按照新的realeSize申请内存空间,创建dictht,并赋值给dict.ht[1]

  • 设置dict.rehashidx = 0,标示开始rehash

  • 将dict.ht[0]中的每一个dictEntry都rehash到dict.ht[1]

  • 将dict.ht[1]赋值给dict.ht[0],给dict.ht[1]初始化为空哈希表,释放原来的dict.ht[0]的内存

  • 将rehashidx赋值为-1,代表rehash结束

  • 在rehash过程中,新增操作,则直接写入ht[1],查询、修改和删除则会在dict.ht[0]和dict.ht[1]依次查找并执行。这样可以确保ht[0]的数据只减不增,随着rehash最终为空

整个过程可以描述成:
在这里插入图片描述


总结

Dict的结构:

  • 类似java的HashTable,底层是数组加链表来解决哈希冲突
  • Dict包含两个哈希表,ht[0]平常用,ht[1]用来rehash

Dict的伸缩:

  • 当LoadFactor大于5或者LoadFactor大于1并且没有子进程任务时,Dict扩容
  • 当LoadFactor小于0.1时,Dict收缩
  • 扩容大小为第一个大于等于used + 1的2^n
  • 收缩大小为第一个大于等于used 的2^n
  • Dict采用渐进式rehash,每次访问Dict时执行一次rehash
  • rehash时ht[0]只减不增,新增操作只在ht[1]执行,其它操作在两个哈希表

在这里插入图片描述


相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-04-27 23:08:03       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-27 23:08:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-27 23:08:03       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-27 23:08:03       20 阅读

热门阅读

  1. 数据结构中的栈和队列(附实际案例代码)

    2024-04-27 23:08:03       14 阅读
  2. 【QT】QPointF、QRectF、QPolygonF 介绍

    2024-04-27 23:08:03       12 阅读
  3. 如何读取一个整行的字符串

    2024-04-27 23:08:03       13 阅读
  4. 顺序排列的二叉树的删除

    2024-04-27 23:08:03       9 阅读
  5. 如何用代码制作一个想要的网站?

    2024-04-27 23:08:03       11 阅读
  6. 状态模式:管理状态转换的策略

    2024-04-27 23:08:03       13 阅读
  7. 请求头headers中的信息

    2024-04-27 23:08:03       10 阅读
  8. SpringBoot的核心内容之自动装配

    2024-04-27 23:08:03       10 阅读
  9. C# 学习笔记

    2024-04-27 23:08:03       11 阅读
  10. C# Solidworks二次开发:枚举应用实战(第六讲)

    2024-04-27 23:08:03       15 阅读