钻研Redis源码,掌握Dict结构(redis源码 dict)

钻研Redis源码,掌握Dict结构

Redis作为一种高性能的key-value存储系统,被广泛应用于数据缓存、消息队列等场景。其核心数据结构包括String、List、Set、ZSet和Hash等类型,在Redis的代码实现中,很多数据结构采用C语言实现。其中,Dict结构作为Redis中常用的哈希表,被广泛使用。本文将介绍Dict的结构、原理和实现,并且详细探讨Dict的部分源码,希望对读者了解Redis的数据结构有所帮助。

1. Dict结构

在源码中,Dict结构被定义在dict.h文件中。Dict是一个哈希表的结构体,包含以下几个成员:

“`c

typedef struct dictEntry {

void *key;

union {

void *val;

uint64_t u64;

int64_t s64;

double d;

} v;

struct dictEntry *next;

} dictEntry;

typedef struct dictType {

uint64_t (*hashFunction)(const void *key);

void *(*keyDup)(void *privdata, const void *key);

void *(*valDup)(void *privdata, const void *obj);

int (*keyCompare)(void *privdata, const void *key1, const void *key2);

void (*keyDestructor)(void *privdata, void *key);

void (*valDestructor)(void *privdata, void *obj);

} dictType;

typedef struct dictht {

dictEntry **table;

unsigned long size;

unsigned long sizemask;

unsigned long used;

} dictht;

typedef struct dict {

dictType *type;

void *privdata;

dictht ht[2];

long rehashidx;

unsigned long iterators;

} dict;


其中,dictEntry结构体表示哈希表中的一个键值对,包含键、值、指向下一个dictEntry的指针等成员;dictType结构体用于定义字典操作的相关函数,比如哈希函数、键值复制函数和键值比较函数等;dictht结构体则是哈希表的关键结构体,包含哈希桶指针数组、桶大小、桶数量等成员;而dict则包含dictType、dictht等成员,用于表示一个完整的字典结构。

2. 原理

Dict通过哈希表实现快速查找键值对。哈希表是一种用于实现关联数组的数据结构,其基本思路是将键通过哈希函数转换成索引,存放在哈希桶中,从而实现快速的查找和插入。Dict中的哈希桶使用指针数组来存储,每个哈希桶元素对应一个dictEntry结构体。当插入或查找键值对时,先通过哈希函数计算出对应的哈希值,并将其映射到哈希桶上,找到对应的桶元素指针,然后在桶中查找或插入dictEntry。

为了解决哈希冲突的问题,Dict中使用了拉链法作为哈希桶的冲突解决方法。当多个键值对的哈希值相同时,将这些键值对通过一个链表连接在一起,从而解决了哈希冲突问题。

3. 实现

Dict的源码实现分为几个部分,包括初始化、添加、删除、查找、哈希冲突处理等。下面我们通过具体的代码实例来详细介绍Dict的源码实现。

初始化

Dict的初始化主要是对哈希桶进行初始化,同时设置字典类型和哈希扩展因子等信息。下面是Dict初始化代码的实现:

```c
// 初始化一个新的字典
dict *dictCreate(dictType *type, void *privDataPtr)
{
dict *d = zmalloc(sizeof(*d));
_dictInit(d,type,privDataPtr);
return d;
}
// 配置字典信息
void _dictInit(dict *d, dictType *type, void *privdata)
{
// 对两张哈希表分别进行初始化操作
_dictReset(&d->ht[0]);
_dictReset(&d->ht[1]);
// 设置字典类型信息
d->type = type;
// 设置字典类型私有数据
d->privdata = privdata;
d->rehashidx = -1;
d->iterators = 0;
}

添加

Dict的添加操作主要是对键值对进行哈希计算,并将该键值对插入到对应的哈希桶中。如果哈希冲突,则将该键值对插入到链表的尾部,如果链表中已经存在相同的键,则更新该键所对应的值。

“`c

int dictAdd(dict *d, void *key, void *val)

{

dictEntry *entry = dictAddRaw(d,key,NULL);

if (!entry) return DICT_ERR;

// 更新值

dictSetVal(d, entry, val);

return DICT_OK;

}

dictEntry *dictAddRaw(dict *d, void *key, dictEntry **existing)

{

long index;

dictEntry *entry;

dictht *ht;

if (dictIsRehashing(d))

_dictRehashStep(d);

// 找到kv对应的table index

if ((index = _dictKeyIndex(d, key, dictHashKey(d, key), existing)) == -1)

return NULL;

// 计算kv对应bucket

ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];

entry = zmalloc(sizeof(*entry));

entry->next = ht->table[index];

ht->table[index] = entry;

ht->used++;

dictSetKey(d, entry, key);

return entry;

}


删除

Dict中的删除操作主要涉及到对哈希桶中相应键值对的删除。对于通过哈希计算得到的键值对,我们可以直接在哈希桶中删除,如果是在哈希冲突链表中的键值对,则需要先查找链表中的该键值对,在将其删除。具体代码实现如下:

```c
int dictDelete(dict *d, const void *key)
{
return dictGenericDelete(d,key,NULL);
}

int dictGenericDelete(dict *d, const void *key, dictEntry **existing)
{
unsigned long h, idx;
dictEntry *he, *prevHe;
int table;
// 确定删除的位置以及table
if (d->ht[0].used == 0 && d->ht[1].used == 0) return DICT_ERR;

if (dictIsRehashing(d)) _dictRehashStep(d);
h = dictHashKey(d, key);
for (table = 0; table
idx = h & d->ht[table].sizemask;
he = d->ht[table].table[idx];
prevHe = NULL;
while(he) {
if (key==he->key || dictCompareKeys(d, key, he->key)) {
if (existing)
*existing = he;
if (prevHe)
prevHe->next = he->next;
else
d->ht[table].table[idx] = he->next;
if (d->type->keyDestructor)
d->type->keyDestructor(d->privdata, he->key);
if (d->type->valDestructor)
d->type->valDestructor(d->privdata, he->v.val);
zfree(he);
d->ht[table].used--;
return DICT_OK;
}
prevHe = he;
he = he->next;
}
if (!dictIsRehashing(d)) break;
}
return DICT_ERR;
}

查找

Dict中的查找操作是对键值对的查询,通过哈希函数得到该键对应的哈希桶,再在哈希桶中查找该键值对。具体代码实现如下:

“`c

dictEntry *dictFind(dict *d, const void *key)

{

dictEntry *he;

香港服务器首选树叶云,2H2G首月10元开通。
树叶云(shuyeidc.com)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/263738.html<

(0)
运维的头像运维
上一篇2025-05-04 17:11
下一篇 2025-05-04 17:12

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注