HashTable
我们之前讲的Redis对象Hash这些是一种数据类型而今天这个学习笔记hashtable是这些类型的具体底层实现。注意要辨别。那么第一个问题什么是HASHTABLE?HASHTABLE可以想象成目录要翻看什么内容直接通过目录能找到页数翻过去看。如果没有目录我们需要一页一页往后翻效率很低。在计算机世界里HASHTABLE就扮演着这样一个快速索引的角色通过HASHTABLE我们可以只用O(1)时间复杂度就能快速找到key对应的value。接着我们看第二个问题即HASHTABLE的结构/* This is our hash table structure. */ typedef struct dictt { dictEntry **table; unsigned long size; unsigned long sizemask; unsigned long used; } dictt;最外层是一个封装的dictht结构具体的字段含义如下:table:指向实际hash存储。存储可以看做一个数组所以是*table的表示石C语言中*table可以表示一个数组。size:哈希表大小。实际就是dictEntry有多少元素空间。size是桶数不包含链表上的节点sizemask: 哈希表大小的掩码表示总是等于size-1。这个属性和哈希值一起决定一个键应该被放到table数组的哪个索引上面规则Indexhashsizemask。used:表示已有节点数量。通过这个字段可以很方便地查询到目前HASHTABLE元素总量。由上述的定义我们可以知道used的数量可能大于size进入第三个知识点Hash表渐进式扩容:渐进式扩容顾名思义就是一点一点慢慢扩容而不是一股脑直接做完那具体流程是怎样的呢?其实为了实现渐进式扩容Redis中没有直接把dictht暴露给上层而是再封装了一层:可以看到dict结构里面包含了两个dictht结构也就是2个HASHTABLE结构。dictEntry是链表结构也就是用拉链法解决Hash冲突用的是头插法。实际上平常使用的就是一个HASHTABLE在触发扩容之后就会两个HASHTABLE同时使用详细过程是这样的:当向字典添加元素时发现需要扩容就会进行Rehash。Rehash的流程大概分成三步:首先为新Hash表ht[1]分配空间。新表大小为第一个大于等于原表2倍used的2次方幂。举个例子原表如果used5002倍就是1000那第一个大于1000的2次方幂则为1024。此时字典同时持有ht[0]和ht[1]两个哈希表。字典的偏移索引rehashidx从静默状态-1设置为0表示Rehash工作正式开始。我们来观察一下rehashidx在途中状态的变化:初始状态在开始 rehash 之前rehashindex被设置为 -1表示没有进行 rehash。当需要开始 rehash 时rehashindex被设置为 0第一个桶索引为0开始移。迁移过程每次执行增、删、查、改等操作时Redis 会顺带迁移rehashindex所指向的桶中的所有键值对到新的哈希表。迁移完一个桶后rehashindex会加1指向下一个桶。这样每次操作只迁移一个桶避免了集中迁移导致的长时间阻塞。完成迁移当rehashindex递增到超过旧哈希表的大小size时表示所有桶都已经迁移完毕。此时rehash 完成旧哈希表被释放新哈希表替换旧哈希表rehashindex被重置为 -1。关于空桶的处理在迁移过程中如果当前rehashindex指向的桶是空的那么 Redis 会跳过这个桶并将rehashindex加1继续检查下一个桶。这样可以确保迁移过程不会因为遇到空桶而停滞直到所有非空桶都被迁移。随着字典操作的不断执行最后会在某个时间点ht[0]的所有键值对被rehash至ht[1],此时h[1]会替代h[0]然后rehashidx被设置为-1代表扩容结束停止时机触发条件rehashidx值ht[0].used正常完成所有键已迁移 size 0提前完成中途used0 size 0空桶限制遇到太多空桶 size 0遍历完成达到size边界 size应该0总结一下渐进式扩容的核心就是操作时顺带迁移。讲了扩容是怎么实现的肯定大家会想着我们啥时候会进行扩容呢?这就是我们最后一个学习的问题扩容与缩容时机是什么时候?Redis提出了一个负载因子的概念负载因子表示目前RedisHASHTABLE的负载情况是游刃有余还是不堪重负了。我们设负载因子为k那么kht[0].used/ht[0].size也就是使用空间和总空间大小的比例。Redis会根据负载因子的情况来扩容:负载因子大于等于1说明此时空间已经非常紧张。新数据是在链表上叠加的越来越多的数据其实无法在0(1)时间复杂度找到还需要遍历一次链表如果此时服务器没有执行BGSAVE或BGREWRITEAOF这两个命令就会发生扩容。负载因子大于5这时候说明HASHTABLE真的已经不堪重负了此时即使是有复制命令在进行也要进行Rehash扩容。Redis的扩容策略基于负载因子和写时复制机制的权衡当负载因子≥1时哈希表性能开始下降本应触发扩容但如果此时正在执行BGSAVE或BGREWRITEAOF会fork子进程并使用写时复制技术扩容将导致内存页被大量修改使内存占用量短时间内近翻倍增长因此Redis选择暂不扩容以优先保证内存稳定而当负载因子≥5时哈希表性能已严重恶化即便有子进程运行Redis也会强制扩容因为此时性能损失已远超内存增长的成本。扩容是数据太多存不下了那如果太富裕呢比如原来可能数据较多发生了扩容但后面数据不再需要被删除了此时多余的空间就是一种浪费。缩容过程其实和扩容是相似的也是渐进式缩容这里不赘述。同样的Redis还是用负载因子来控制什么时候缩容:当负载因子小于0.1即负载率小于10%此时进行缩容新表大小为第一个大于等于原表used的2次方幂。当然如果有BGSAVE或BGREWRITEAOF这两个复制命令缩容也会受影响不会进行。声明: 本篇笔记仅为学习时整理的笔记以及疑问解决点无其他任何商业用途如有侵权联系即删。

相关新闻

AI核心知识84——大语言模型之 AI Constitution(简洁且通俗易懂版)

AI核心知识84——大语言模型之 AI Constitution(简洁且通俗易懂版)

AI 宪法 (AI Constitution) 是由 AI 公司 Anthropic(Claude 的开发商)首创并推广的一个核心概念,它代表了 AI 对齐技术的一次重大飞跃。 简单来说,AI 宪法就是给 AI 模型制定的一套“根本大法”或“最高行为准则”。 它的核心理…

2026/7/6 7:59:14 阅读更多 →
AI核心知识83——大语言模型之 AI伦理审查员(简洁且通俗易懂版)

AI核心知识83——大语言模型之 AI伦理审查员(简洁且通俗易懂版)

AI伦理审查员 (AI Ethics Auditor / Reviewer) 是人工智能时代诞生的“数字守门人”和“道德质检员”。如果说AI工程师负责让AI变得“更强、更快” (性能维度),那么AI伦理审查员就是负责确保AI“更善、更安全” (价值观维度&#…

2026/7/5 8:57:53 阅读更多 →
stm32的ADC模块在进行单通道ADC测量时,悬空接地电压在OLED显示屏上显示为3.3V,而不是实际的电压值,如何解决?

stm32的ADC模块在进行单通道ADC测量时,悬空接地电压在OLED显示屏上显示为3.3V,而不是实际的电压值,如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者&…

2026/7/4 22:23:54 阅读更多 →

最新新闻

Windows右键菜单深度解析:从杂乱到有序的工作流重构实践

Windows右键菜单深度解析:从杂乱到有序的工作流重构实践

Windows右键菜单深度解析:从杂乱到有序的工作流重构实践 【免费下载链接】ContextMenuManager 🖱️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 作为Windows用户,你是否经历过这…

2026/7/6 8:17:47 阅读更多 →
SQL集合运算符深度解析:UNION、INTERSECT、EXCEPT原理与避坑指南

SQL集合运算符深度解析:UNION、INTERSECT、EXCEPT原理与避坑指南

1. 为什么我坚持把 SQL 集合运算符讲透——不是为了炫技,而是因为90%的日常数据清洗都卡在这一步 你有没有遇到过这样的场景:老板甩来两份Excel表格,一份是上季度新注册用户,一份是本月完成首单的用户,让你“快速拉个名…

2026/7/6 8:17:47 阅读更多 →
Dify低代码AI应用开发实战:30+项目手把手教学,一周掌握企业级应用搭建

Dify低代码AI应用开发实战:30+项目手把手教学,一周掌握企业级应用搭建

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 这次我们来看一个面向 AI 应用开发的实战教程资源。这个资源的核心不是某个单一的模型或工具,而是一套系统化的视频课程&a…

2026/7/6 8:15:25 阅读更多 →
笨阶乘C++解法详解(力扣1006)

笨阶乘C++解法详解(力扣1006)

问题解析:LeetCode 1006 “笨阶乘”要求对正整数 N 按递减顺序依次使用乘 *、除 /、加 、减 - 四个运算符循环计算,即 clumsy(N) N * (N-1) / (N-2) (N-3) - (N-4) * (N-5) / (N-6) ...,需返回计算结果。核心在于处理运算符优先级&#xf…

2026/7/6 8:13:24 阅读更多 →
我们打工人用好 WorkBuddy 这 5 个实用技能,轻松工作提效

我们打工人用好 WorkBuddy 这 5 个实用技能,轻松工作提效

大家好,我是赛博李同学。腾讯的 WorkBuddy 功能进化的非常之快,俨然它已经成为我日常办公小助手了,真正的生产力工具!今天就分享5个我天天在用的技能。没什么高深的东西,就是些实打实能帮你把时间抠出来的小活儿。一、…

2026/7/6 8:11:23 阅读更多 →
借助生成式 AI 和压缩算法,仅用 500 字节构建世界地图!

借助生成式 AI 和压缩算法,仅用 500 字节构建世界地图!

【导语:2026 年 6 月 28 日消息,有人曾在 JS1k 竞赛中用不到 1000 字节构建世界地图,如今借助生成式 AI 和压缩算法,成功将地图数据压缩至不到 500 字节,引发关注。】从 1000 字节到挑战 500 字节10 多年前&#xff0c…

2026/7/6 8:11:23 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻