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

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
全局流量管理 GTM,标准版 1个月
简介: 【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)

【专栏简介】

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

【技术大纲】

为何Redis备受瞩目?原因在于其学习曲线平缓,短时间内便能对Redis有初步了解。同时,Redis在处理特定问题时展现出卓越的通用性,专注于其擅长的领域。深入了解Redis后,您将能够明确哪些任务适合由Redis承担,哪些则不适宜。这一经验对开发人员来说是一笔宝贵的财富。

在这个专栏中,我们将专注于Redis的6.2版本进行深入分析和介绍。Redis 6.2不仅是我个人特别偏爱的一个版本,而且在实际应用中也被广泛认为是稳定性和性能表现都相当出色的版本

【专栏目标】

本专栏深入浅出地传授Redis的基础知识,旨在助力读者掌握其核心概念与技能。深入剖析了Redis的大多数功能以及全部多机功能的实现原理,详细展示了这些功能的核心数据结构和关键算法思想。读者将能够快速且有效地理解Redis的内部构造和运作机制,这些知识将助力读者更好地运用Redis,提升其使用效率。

将聚焦于Redis的五大数据结构,深入剖析各种数据建模方法,并分享关键的管理细节与调试技巧。

【目标人群】

Redis技术进阶之路专栏:目标人群与受众对象,对于希望深入了解Redis实现原理底层细节的人群

1. Redis爱好者与社区成员

Redis技术有浓厚兴趣,经常参与社区讨论,希望深入研究Redis内部机制、性能优化和扩展性的读者。

2. 后端开发和系统架构师

在日常工作中经常使用Redis作为数据存储和缓存工具,他们在项目中需要利用Redis进行数据存储、缓存、消息队列等操作时,此专栏将为他们提供有力的技术支撑。

3. 计算机专业的本科生及研究生

对于学习计算机科学、软件工程、数据分析等相关专业的在校学生,以及对Redis技术感兴趣的教育工作者,此专栏可以作为他们的学习资料和教学参考。

无论是初学者还是资深专家,无论是从业者还是学生,只要对Redis技术感兴趣并希望深入了解其原理和实践,都是此专栏的目标人群和受众对象

让我们携手踏上学习Redis的旅程,探索其无尽的可能性!


字典

字典,作为一种抽象数据结构,常常被我们程序员称之为Hash或者映射,主要用于存储键值对。在字典中,每个键都是唯一的,与之对应着一个值,这种

键与值的配对关系被称为键值对。


凭借这种键值对的关系,程序能够轻松地在字典中根据键查找对应的值,或者通过键来更新值,甚至删除整个键值对。这种灵活的操作方式使得字典在编程中发挥着重要的作用。

虽然许多高级编程语言内置了字典这种数据结构,但Redis所使用的C语言却并未提供内置支持。因此,Redis为了实现其高效的数据存储和操作需求,自行构建了字典数据结构。

这种设计旨在优化数据存储和访问效率,确保在复杂数据场景下,Redis 依然能够保持高效稳定的性能表现。通过深度整合字典数据结构,Redis 成功实现了对大量键值对的高效管理,进一步提升了其在各种应用场景中的实用价值。

字典和Hash的结构关系

字典作为哈希键的底层实现之一,在特定情况下发挥着关键作用。当哈希键中包含的键值对数量庞大,或者键值对中的元素为较长字符串时,Redis 会选择采用字典作为其底层实现。

Hash结构的实现

Redis 成功构建了一个强大而灵活的 Hash 表实现,为存储和检索键值对提供了高效的支持。无论是简单的数据操作还是复杂的查询任务,Redis 的 Hash 源码都能够满足需求,展现出其出色的性能和稳定性。

源码分析

Hash 源码主要由两部分组成:dict.hdict.c

  • dict.h 文件主要负责定义 Hash 表的结构、哈希项,以及声明了一系列针对 Hash 表的操作函数。这些定义和声明为开发者提供了一个清晰的接口,使他们能够了解和使用 Hash 表的功能。
  • dict.c 文件则是对这些函数的具体实现。它包含了 Hash 表创建、查找、插入、删除等操作的实现细节,确保 Hash 表能够高效、稳定地运行。
Hash数据结构

dict.h 文件中,Hash 表是通过一个(dictEntry **table)来构建的,这种设计使得哈希表的实现更加高效且灵活。总体个人认为分为数据结构模型+行为操作模型两个大部分:


Redis字典结构定义

dict结构通过dictType指针抽象键值对类型及操作,实现多样化处理。采用双哈希表实现渐进式rehashing,确保扩容缩容平稳进行,减少性能损耗。下面是对应的dict的源码,我在其中加入了注释,进行介绍对应的含义:

c

复制代码

struct dict {  
    // 指向 dictType 结构体的指针,包含与字典相关的类型特定函数和操作  
    dictType *type;  
    // 字典的哈希表数组,用于支持渐进式 rehashing,包含两个哈希表  
    dictEntry **ht_table[2];  
    // 哈希表已使用的槽位数量数组  
    unsigned long ht_used[2];  
    // rehashing 索引,如果 rehashing 未进行,则值为 -1  
    long rehashidx;   
    // 暂停rehashing的标志位,大于0时暂停rehashing,小于0表示代码错误  
    int16_t pauserehash;   
    // 哈希表大小的指数(size = 1 << exp),包含两个哈希表的大小指数  
    signed char ht_size_exp[2];   
    // 暂停自动调整大小的标志位,大于 0 时禁用自动调整大小,小于 0 表示代码错误  
    int16_t pauseAutoResize;   
    // 柔性数组,用于存储与字典相关的元数据,在标准的 Redis 实现中可能并未使用  
    void *metadata[];  
};
  • dictEntry **ht_table[2]:dictEntry **table 是个二维数组,其中第一维是 bucket,每一行就是 bucket 指向的元素列表(因为键哈希冲突,Redis 采用了链式哈希)。
  • ht_used[2]:这是一个数组,记录了每个哈希表当前已使用的槽位数量。这对于管理哈希表的容量和进行rehashing操作非常重要。提供字典了解当前哈希表的使用情况,以便在必要时进行扩容或缩容。
  • rehashidx:这是一个索引值,用于指示当前 rehashing 操作的进度。如果 rehashing 未进行,则值为 -1。在渐进式 rehashing 过程中,该值会逐渐从 0 增加到旧哈希表的长度,表示已经迁移了多少个键值对。使得字典可以在多个操作之间保持 rehashing 的状态。
dictType结构体的指针

dictType与字典紧密相关的特定类型函数和操作,这些函数和操作定义了字典的行为,确保它能够有效地处理各种与字典相关的任务。支持的功能如下图所示:


下面展示的是Redis的源代码片段,我结合个人理解,为其添加了详尽的注释,旨在帮助大家更好地把握其深层含义,促进代码的解读与理解。

c

复制代码

typedef struct dictType {  
    /* 回调函数组 */  
    /* 哈希函数,用于将键(key)转化为哈希值 */  
    uint64_t (*hashFunction)(const void *key);  
    /* 键的复制函数,用于在字典中创建键的副本 */  
    void *(*keyDup)(dict *d, const void *key);  
    /* 值的复制函数,用于在字典中创建值的副本 */  
    void *(*valDup)(dict *d, const void *obj);  
    /* 键的比较函数,用于比较两个键是否相等 */  
    int (*keyCompare)(dict *d, const void *key1, const void *key2);  
    /* 键的析构函数,用于释放键所占用的内存 */  
    void (*keyDestructor)(dict *d, void *key);  
    /* 值的析构函数,用于释放值所占用的内存 */  
    void (*valDestructor)(dict *d, void *obj);  
    /* 是否允许调整字典大小的函数,基于更多的内存需求和当前使用比率 */  
    int (*resizeAllowed)(size_t moreMem, double usedRatio);  
    /* 在字典初始化或重新哈希开始时调用的函数(旧的和新的哈希表已经创建) */  
    void (*rehashingStarted)(dict *d);  
    /* 在字典初始化或所有条目从旧哈希表到新哈希表重新哈希完成时调用的函数。两个哈希表都还存在,  
     * 并在此回调函数之后被清理。 */  
    void (*rehashingCompleted)(dict *d);  
    /* 允许字典携带额外的调用者定义的元数据。当分配字典时,额外的内存被初始化为0。 */  
    size_t (*dictMetadataBytes)(dict *d);  
    /* 数据 */  
    /* 用户自定义数据,可以在字典中使用 */  
    void *userdata;  
    /* 标志位 */  
    /* 'no_value'标志位,如果设置,表示不使用值,即字典是一个集合(set)。  
     * 当此标志位设置时,无法访问dictEntry的值,也无法使用dictSetKey()。  
     * 同样,也无法使用条目元数据。 */  
    unsigned int no_value:1;  
    /* 如果no_value = 1且所有键都是奇数(最低有效位=1),设置keys_are_odd = 1  
     * 可以启用另一个优化:在不分配dictEntry的情况下存储键。 
     */  
    unsigned int keys_are_odd:1;  
    /* TODO: 添加一个'keys_are_even'标志位,并在设置该标志位时使用类似的优化。 */  
} dictType;

希望这些注释能为大家的学习和工作提供便利,大家对于源码的头文件的理解,主要要集中于有哪些方法以及支持哪些操作即可。

dictEntry二维数组

dictEntry **table 作为一个二维数组,其第一维代表的是不同的 bucket(桶)。每个 bucket 内部则通过指针链接了一系列元素,形成链表结构。



如上图所示,对应的dicEntity数组中每个元素都是一个指向 dictEntry 链表的指针。


【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(二)https://developer.aliyun.com/article/1471153


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
14天前
|
机器学习/深度学习 人工智能 自然语言处理
AI技术深度解析:从基础到应用的全面介绍
人工智能(AI)技术的迅猛发展,正在深刻改变着我们的生活和工作方式。从自然语言处理(NLP)到机器学习,从神经网络到大型语言模型(LLM),AI技术的每一次进步都带来了前所未有的机遇和挑战。本文将从背景、历史、业务场景、Python代码示例、流程图以及如何上手等多个方面,对AI技术中的关键组件进行深度解析,为读者呈现一个全面而深入的AI技术世界。
80 10
|
27天前
|
机器学习/深度学习 人工智能 PyTorch
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
本文探讨了Transformer模型中变长输入序列的优化策略,旨在解决深度学习中常见的计算效率问题。文章首先介绍了批处理变长输入的技术挑战,特别是填充方法导致的资源浪费。随后,提出了多种优化技术,包括动态填充、PyTorch NestedTensors、FlashAttention2和XFormers的memory_efficient_attention。这些技术通过减少冗余计算、优化内存管理和改进计算模式,显著提升了模型的性能。实验结果显示,使用FlashAttention2和无填充策略的组合可以将步骤时间减少至323毫秒,相比未优化版本提升了约2.5倍。
43 3
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
|
7天前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
44 1
|
21天前
|
机器学习/深度学习 人工智能 自然语言处理
秒级响应 + 99.9%准确率:法律行业文本比对技术解析
本工具基于先进AI技术,采用自然语言处理和语义匹配算法,支持PDF、Word等格式,实现法律文本的智能化比对。具备高精度语义匹配、多格式兼容、高性能架构及智能化标注与可视化等特点,有效解决文本复杂性和法规更新难题,提升法律行业工作效率。
|
18天前
|
数据采集 存储 JavaScript
网页爬虫技术全解析:从基础到实战
在信息爆炸的时代,网页爬虫作为数据采集的重要工具,已成为数据科学家、研究人员和开发者不可或缺的技术。本文全面解析网页爬虫的基础概念、工作原理、技术栈与工具,以及实战案例,探讨其合法性与道德问题,分享爬虫设计与实现的详细步骤,介绍优化与维护的方法,应对反爬虫机制、动态内容加载等挑战,旨在帮助读者深入理解并合理运用网页爬虫技术。
|
24天前
|
机器学习/深度学习 自然语言处理 监控
智能客服系统集成技术解析和价值点梳理
在 2024 年的智能客服系统领域,合力亿捷等服务商凭借其卓越的技术实力引领潮流,它们均积极应用最新的大模型技术,推动智能客服的进步。
64 7
|
29天前
|
负载均衡 网络协议 算法
Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式
本文探讨了Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式,以及软件负载均衡器、云服务负载均衡、容器编排工具等实现手段,强调两者结合的重要性及面临挑战的应对措施。
67 3
|
1月前
|
网络协议 网络性能优化 数据处理
深入解析:TCP与UDP的核心技术差异
在网络通信的世界里,TCP(传输控制协议)和UDP(用户数据报协议)是两种核心的传输层协议,它们在确保数据传输的可靠性、效率和实时性方面扮演着不同的角色。本文将深入探讨这两种协议的技术差异,并探讨它们在不同应用场景下的适用性。
71 4
|
1月前
|
安全 持续交付 Docker
深入理解并实践容器化技术——Docker 深度解析
深入理解并实践容器化技术——Docker 深度解析
62 2
|
1月前
|
供应链 算法 安全
深度解析区块链技术的分布式共识机制
深度解析区块链技术的分布式共识机制
56 0

推荐镜像

更多