Redis-字典数据结构-源码深入解析

Redis 源码硬核解析系列专题 - 第三篇:核心数据结构之字典(Dict) 字典的定义在src/dict.h和src/dict.c中。代码片段dict.hvoid *key;// 键union {void *val;// 值double d;} v;// 链表,解决哈希冲突// 哈希表数组// 哈希表大小// 大小掩码,用于计算索引// 已使用槽数} dictht;// 类型特定函数(如自定义哈希)// 私有数据// 两个哈希表,用于rehash// rehash进度,-1表示未进行} dict;硬核解析dictEntry:键值对节点, 阅读详情

1.Redis的字典是什么?

Redis字典,又叫符号表/关联数组/映射,是一种用于保存键值对的抽象数据结构。还可以作为Redis数据库的底层,哈希键的底层等。

2.如何实现Redis字典

自顶向下来实现一个Redis字典,使用Redis的实现语言-C语言

1)字典

typedef struct dict{
	dicType *type;//类型特定函数
	void *privdata;//私有数据
	dictht ht[2];//哈希表
	int trehashidx;//rehash索引,当rehash不再进行时,值为-1
}
  • type属性和privdata属性是针对不同类型的键值对,为创建多态字典而设置的:
    – privdata属性:保存了需要传给那些特定类型函数(见下)的可选参数
    – type属性:指向一个dictType结构的指针,每个该结构都保存了一簇用于操作特定类型的键值对的函数,Redis自动为不同的字典类型设置类型特定函数`
typedef struct dictType{
	unsigned int (*hashFunction)(const void *key);//计算哈希值的函数
	void *(*keyDup)(void*privdata,const void *key);//复制键的函数
	void *(*valueDup)(void*privdata,const void *obj);//复制值的函数
	int (*keyCompare)(void *privadata,const void *key1,const void *key2);//对比值的函数
	int (*keyDestructor)(void *privdata,void *key);//销毁键的函数
	int (*valDestructor)(void *privdata,void *obj);//销毁值的函数

  • ht属性是包含了两个项的数组,每个项都是一个dictht哈希表(详情见下)。一般情况,字典只使用ht[0]哈希表,ht[1]哈希表只会在对ht[0]进行rehash的时候使用。
  • rehashidx属性也是和rehash有关的,记录了当前rehash的进度,默认是-1。
    普通状态下的字典
    上图是普通状态下的字典,箭头表示将表中的小项进行展开,本节也是按照这种结构撰写的

2)哈希表

Redis字典的底层数据结构包括哈希表结构

typedef struct dictht{
	dictEntry **table;//哈希表数组
	unsigned long size;//哈希表大小
	unsigned long sizemask;//哈希表大小掩码,用于计算索引值。sizemask = size - 1;
	unsigned long used;//该哈希表已有的节点的数量
}

哈希表数组table的每个元素指向一个dictEntry结构,也就是哈希表节点

3)哈希表节点

字典以哈希表作为底层实现,一个哈希表包括多个哈希节点,一个哈希节点保存一个字典中的键值对。

typedef struct dictEntry{
	void *key;//键
	/*值*/
	union{//三种类型的数据
		void *val;
		unit64_t u64;
		int64_t s64;
	}v;//值的名字,有以上三种选择
	struct dictEntry *next;//指向下一个哈希节点,形成链表,解决哈希冲突问题,关于哈希冲突将在下边进行介绍
}

3.哈希算法

1)什么是哈希算法

  • 在学习HashMap的时候我们对hash算法有了一定的了解.。 在Redis中,当一个新的键值添加到字典中时,程序会根据键值对的键计算出哈希值和索引值,根据索引值将包含新键值对的哈希表节点放入 哈希表数组 的指定索引上。
  • 键的哈希值使用哈希函数hash=dict->type->hashFunction(key)计算,之后通过哈希表的sizemask属性值和哈希值,使用公式index=hash&dict->ht[x].sizemask计算出索引值,其中ht[x]中的x可能是0或1。
  • 关于MurmurHash算法可以看这个网站:算法主页

2)如何解决哈希冲突

  • 哈希冲突:当两个及以上的键被分配到哈希表数组的同一个索引上面时,这些键发生哈希冲突。
  • Redis哈希表使用链地址法解决键冲突:前边讲哈希表节点的结构时讲过,哈希表节点有一个next指针指向下一个哈希节点,多个哈希表节点可以用指针构成一个单项链表,针对分配到同一个索引上的多个节点可以奖它们用链表连接,这样就有效解决了哈希冲突问题。
  • 一些使用中的惯例:新添加的节点要添加到链表的表头位置,因为dictEntry节点没有指向表尾的指针。

3)rehash

  • 背景:随着不断的操作,哈希表保存的键值对也在增加/减少,为了维持哈希表的负载因子在合理的范围内,需要对哈希表的大小进行管理:键值对数量过多就扩展,数量过少就收缩。
  • 以上工作都是通过rehash(重新散列)操作完成,rehash的步骤如下:
    – 1、为字典的ht[1]分配空间:取决于要执行和操作、ht[0]当前包含键值对的数量。
    如果要扩展哈希表,ht[1]的大小是2的n次方,且恰好大于等于ht[0].used*2的那个
    如果是收缩哈希表,ht[1]的大小是2的n次方,且恰好大于等于ht[0].used的那个
    – 2、将ht[0]上的所有键值对rehash到ht[1]上,rehash就是重新计算键的哈希值和索引值,之后将键值对放在新的哈希表的指定位置上
    – 3、ht[0]的所有键值对迁移到ht[1]之后,释放空表ht[0],将ht[1]设置为ht[0],设置一个空白的哈希表为新的ht[1](为下一次rehash做准备)
  • 什么时候会发生哈希表的扩展?
    – 1、服务器当前没有执行BGSAVE命令/BGREWRITEAOF命令,并且哈希表的负载因子>=1
    – 2、服务器当前正在执行BGSAVE命令/BGREWRITEAOF命令,并且哈希表的负载因子>=5
    负载因子的计算公式如下:
//负载因子 = 哈希表已保存的节点数量 / 哈希表大小
load_factor = ht[0].used / ht[0].size;
  • 什么时候会发生哈希表的收缩?:负载因子 < 0.1时。

4) 渐进式rehash

  • 什么时候使用渐进式rehash?
    当ht[0]的键值对数量不多的时候,可以一次性rehash到ht[1]中。当ht[0]保存的键值对数量到了百万级别这种很大的规模的时候,一次性的rehash到ht[1]中计算量太大可能导致计算机崩溃,这时需要分多次、渐进的将ht[0]的键值对rehash到ht[1]中。
  • 怎么执行渐进式rehash操作?
    1、先根据ht[0]的键值对数量判断是否要执行渐进式rehash,之后为ht[1]分配空间、
    2、在字典中维持一个索引计数器变量rehashidx = 0,表示rehash工作开始
    3、在rehash期间,对字典执行增删改查操作,还会将ht[0]在rehashidx索引上的所有键值对rehash到ht[1]上,rehash完成时rehashidx++
    4、当所有的键值对都被rehash到ht[1]上是,rehashidx = -1表示rehash操作结束
    分治思想在rehash中得到了使用,将操作均摊到每个添加、删除、查找、更新操作上,避免集中式rehash带来的巨大计算量

3.Redis关于字典的API

在这里插入图片描述

Vivado静态时序分析学习笔记(1) 静态时序分析分为片内时序分析(寄存器与寄存器之间的时序关系)和片外时序分析(IO时序分析)。(1)建立时间 setup time在时钟事件(上升沿/下降沿)发生之前数据信号应保持稳定的时间。把实际电路抽象成前级D触发器+组合逻辑+后级D触发器。 阅读详情

相关推荐

TI AWR1642实战指南:CCS调试mmWave Demo Visualizer全流程解析

本文详细解析了TI AWR1642开发板的CCS调试流程,重点介绍了mmWave Demo Visualizer的使用方法。从环境准备、版本确认到bin文件烧录、CCS工程配置,再到调试启动与结果验证,提供了全流程的实战指南,帮助开发者快速掌握AWR1642的调试技巧,避免常见错误。

weixin_30790841的博客 111

Redis经典五大数据类型源码及底层实现

int:保存long型(长整型)的64位(8个字节)有符号整数。只有整数才会使用int,如果是浮点数,Redis内部其实先将浮点数转化为字符串值,然后再保存。- embstr:代表embstr格式的SDS(Simple Dynamic String简单动态字符串),保存长度小于44字节的字符串。EMBSTR顾名思义即:embedded String,表示嵌入式的字符串。raw:保存长度大于44字节的字符串。

Hai_pp的博客 992

AutoCAD 2025在Win10/Win11上的官方安装、配置与问题排查全指南

对于需要在 Windows 11 或 Windows 10 系统上部署 AutoCAD 2025 的设计师、工程师和 IT 支持人员来说,一个稳定、合规的安装流程是高效工作的基石。网络上充斥着各种所谓的“免费下载”和“一键安装”教程,但这些资源往往来源不明,可能捆绑恶意软件、导致软件崩溃,甚至引发严重的许可合规风险。本文旨在提供一个清晰、安全、基于官方最佳实践的 AutoCAD 2025 安装与配置指南,重点解决在 Windows 11 和 Windows 10 系统上部署时可能遇到的兼容性问题、安装失败以

weixin_34396103的博客 448

【Redis】Redis 底层的数据结构(结合源码)

Redis 底层数据结构详解

秋玄的博客 1430

从FER2013到AffectNet:表情识别数据集十年演进史与你的项目选型攻略

本文回顾了从FER2013到AffectNet等主流人脸表情识别数据集的十年演进历程,详细分析了各数据集的特点、适用场景及技术突破。针对不同项目需求,提供了从移动端应用到高精度研究的选型策略,特别强调AffectNet在现代FER项目中的核心价值,并给出混合数据集构建的实战方案。

weixin_26808439的博客 521

Sigmastar平台WDR调试实战:从参数解析到鬼影消除的完整指南

本文提供了Sigmastar平台宽动态(WDR)技术的实战调试指南。针对逆光、运动场景下的核心痛点,系统性地解析了从多曝光采集、HDR融合到色调映射的完整管线,并重点阐述了如何通过调整曝光比、运动阈值与调整曲线等关键参数,有效消除运动鬼影、平衡暗部噪声与细节,最终实现清晰稳定的图像效果。

Jerry的专栏 926

Redis源码解析-基本数据结构

本文主要介绍了 Redis 基础数据结构中的 SDS、字典、IntSet、Object等,希望能够帮助到大家

CrazyRabbitttt 937

CDD那些事 - DID and SecurityAccess

本文介绍了SecurityAccessSID27的安全访问配置流程:1.通过StateGroups添加Level2群组;2.在Classes定义L2子功能;3.配置4步解锁流程,选择对应解锁等级;4.在DiagnosticInstance设置请求响应。同时说明了DID配置的两种方式:在DIDs页面定义或通过Identification页面创建,前者定义更全面。文章还提到ServiceList支持view/edit模式,其中edit模式可配置DID的多服务支持(如同时支持SID22读取和SID2E写入),但该

ziteng21的博客 255

redis核心数据结构源码分析

在 Redis 的实现中,当一个键值对被创建并存储时,键通常是一个字符串,而值则是一个。因此,在dictEntry结构中,key成员指向的是一个字符串,而v.val成员则指向一个。这意味着,当你在 Redis 中存储一个值时,你实际上是在字典中插入一个dictEntry,其中dictEntry的值部分指向一个包含实际数据和元数据的。

m0_73520938的博客 1583

Qt + windows + Linux+QtInstallerFramework打包教程

本文介绍了使用Qt Installer Framework在Windows和Linux系统下打包Qt应用程序的完整教程。Windows部分详细说明了从下载安装框架、配置环境变量、生成release版本,到创建安装包目录结构和修改配置文件的完整流程。Linux部分则重点讲解了环境变量设置、桌面应用配置(.desktop文件)以及两种打包方案:一种使用linuxdeployqt生成AppImage文件,另一种采用类似Windows的安装包方式。教程提供了关键配置文件(config.xml、package.xml

Qt历险记,专注Qt技术,三年医疗设备研发经验,1年机器视觉研发经验,半年柔性传感研发经验。 516

C#实现低通和高通滤波算法

低通滤波器允许通过低于某个截止频率的信号成分,并且抑制高于该频率的成分。而高通滤波器则允许通过高于某个截止频率的信号成分,并抑制低于该频率的成分。巴特沃斯滤波器是一种对称的滤波器,具有平坦的幅度响应和最小的群延迟。低通和高通滤波是数字信号处理中常用的滤波技术,用于滤除或增强信号中的特定频率成分。在本篇文章中,我们将使用C#编程语言来实现低通和高通滤波算法。以上就是使用C#实现低通和高通滤波算法的示例代码。你可以根据自己的需求调整截止频率和采样率,将这些代码应用于你的项目中。是滤波器的截止频率,

XisVisual_Basic的博客 1274

Redis 底层数据结构源码剖析

Redis底层数据结构源码分析

1031

第21章—技术管理篇(上):身为技术人该怎样带好团队并做好管理者

上节讲了职业规划和学习提升这两个话题,随着职业规划的不断落地,或者自己能力的不断提升,大家也会逐渐被提拔成“职级更高”的人。企业规模扩张时,员工数量也会变多,意味着Boss需要更多的人来辅助管理,而管理者会从外部招聘吗?也许会,但大多企业更喜欢从内部选拔,毕竟人的天性更希望找的人值得信赖。此时,一些能力不错、做事靠谱的老员工,就会被“赶上”管理者的位子。作管理不难,但想要“”就需要一定情商。

运维老生常谈 1365

【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)

随着数据需求的迅猛增长,持久化和数据查询技术的重要性日益凸显。关系型数据库已不再是唯一选择,数据的处理方式正变得日益多样化。在众多新兴的解决方案与工具中,Redis凭借其独特的优势脱颖而出。

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。 1387

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【高阶篇】3.5 Redis之底层数据结构字典(Dictionary)详解

上个篇章回顾,我们上个章节,讲了Redis中的快表(QuickList),它是一种特殊的数据结构,用于存储一系列的连续节点,每个节点可以是一个整数或一个字节数组。快表是Redis中的底层数据结构之一,常用于存储有序集合(Sorted Set)等数据类型的底层实现。那么本章讲解Redis中的底层数据结构中的字典(Dictionary)也称为哈希表(Hash Table)。字典(Dictionary)是一种高效的数据结构,用于存储键值对,常用于实现哈希表。

日拱一卒无有尽,功不唐捐终入海 2756

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Redis系列-13.Redis经典五大类型源码及底层实现(一)

RedisObjectt内部对应的3大物理编码ziplist为了节省内存,采用了紧凑的连续存储。ziplist是一个双向链表,可以在时间复杂度为 O(1) 下从头部、尾部进行 pop 或 push。新增或更新元素可能会出现连锁更新现象(致命缺点导致被listpack替换)。不能保存过多的元素,否则查询效率就会降低,数量小和内容小的情况下可以使用。

爱吃知识的土豆倪的博客 2161

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【Redis入门】内部数据结构源码剖析

SDS1.定义SDS(simple dynamic string)即简单动态字符串,在Redis中并没有直接使用C语言传统的字符串表示(以空字符结尾的字符数组),而使用自己构造的SDS。2.源码(1)结构体sds.h/sdshdr的源码如下:/* * 保存字符串对象的结构 */ struct sdshdr { // buf 中已占用空间的长度 int len; // buf

白夜行 966

Redis字典数据结构

参考链接: -- 源码解析:https://www.cnblogs.com/yinbiao/p/10766357.html --结构说明:https://redissrc.readthedocs.io/en/latest/datastruct/dict.html 关键代码位置:src/dict.h 字典是一种键值对映射,但C语言无这种数据结构,Redis自己实现了一套。另外字典是hash的底层实现之一。 数据结构概述说明: - ht数组有两个元素,没有rehash情况下,默认...

Lisam Blog 591

redis 源码讲解开篇

网上各种redis源码讲解,很多质量都非常棒,那我又为什么会再来个redis源码讲解呢;曾几何时,想深究redis源码,网上找相关资料来看,可是看下来总是一知半解,没能相对系统和理解,你应该有和我一样感受吧。原因就是少了实践(让代码跑起来),我要来篇实践性的redis讲解系列来填补这空缺

u010938668的博客 320

Redis源码(1)基本数据结构

Redis源码阅读笔记 文章目录**Redis源码阅读笔记****前言****基本数据结构****动态字符串SDS****结构定义****对比C字符串****接口API****链表List****结构定义****接口API****字典Dict****结构定义****接口API****迭代器****跳跃表skiplist****结构定义****查找、删除、添加节点****接口API****补充:有序集合****HyperLogLog****算法细节****密集存储****稀疏存储****计数缓存****API

青玉白露的博客 334

docker需要多大内存_从源码看redis写入一个key需要多大的内存

上一篇在说redis的bit位操作时候,有一个同学在评论区问到如果mysql有一个g的数据,全部加载到redis需要多大的内存?本文就来一起探讨一下redis中数据是如何存储的,使用内存又是如何计算的,力求讲清楚以下几点内容:从源码看redis的字典redis写入一个key,内存增加了多少?使用redis-benchmark压测看redis内存变化,掌握预估内存的办法本文基于如下环境:操作系统:M...

weixin_33436866的博客 1144

Redis 字典

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34232363的博客 80

(三分钟系列)详解Redis中字典的内部原理和使用方法

前言 在 Redis 中,字典是一种运用特别广泛的数据结构,基本上各个功能模块都有使用到。 主要用途是两个方面 作为数据库键空间 作为 Hash 类型键的底层实现之一 目录 字典的使用示例 字典的底层结构和源码解析 Rehash 的过程 业务场景的实际运用 1. 字典使用示例 1.1 实现数据库键空间 清除数据库里面的所有键值对 redis&gt; FLUSHDB OK ...

weixin_43555803的博客 1058

Redis基础原理

文章目录Redis基础应用用途:缓存、分布式锁字典hash列表list跳跃列表zset计数器Redis原理Redis集群Redis拓展Redis源码 Redis基础应用 用途:缓存、分布式锁 字典hash 1.记录帖子点赞数、评论数、点击数、 2.记录帖子的标题、摘要、作者、封面、展示列表 3.缓存近期热评内容、减少数据库压力 列表list 根据帖子id记录相关帖子 跳跃列表zset ...

qq_42866384的博客 191

Redis 源码分析(1):字典和哈希表(dict.c 和 dict.h)

简介   哈希表是 redis 的核心结构之一,在 redis 的源码中, dict.c 和 dict.h 就定义了 redis 所使用的哈希结构,在这篇文章中,我们将对 dict.c 和 dict.h 进行注解和分析,籍此加深对 redis 的理解。   因为 dict.c 中使用的 separate chaining 哈希表实现可以在任何一本算法书上找到,因此,在本文中没有对查找和增删...

Right Track Wrong Train 664

Redis详细介绍:5种基本数据结构

来源:我没有三颗心脏一、Redis 简介"Redis is an open source (BSD licensed), in-memory data structure sto...

Java知音 803
上一篇: Redis-链表数据结构-深入分析
下一篇: 算法-Binary Prefix Divisible By 5-可被 5 整除的二进制前缀
酱油瓶啤酒杯
博客等级 码龄8年 35粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值