Redis源码分析---字典dict

本文主要分析redis中的dict结构(对应文件dict.h/dict.c)。

一般的dict结构可以利用红黑数实现,STL中的map便是。redis中的dict结构是用哈希表来实现的,键的冲突通过链表来解决。


首先看一些基本结构。

hash表节点结构体,除了kv,还有一个next指针,指向下一个节点(冲突的键是通过链表来解决的)

/*
  * 哈希表节点
  */
 typedef struct dictEntry {
        
     // 键
     void *key;
     // 值
     union {
         void *val;
         uint64_t u64;
         int64_t s64;
     } v;
 
     // 指向下个哈希表节点,形成链表
     struct dictEntry *next;
 
 } dictEntry;


字典特定类型函数结构体。每个特定的字典都需要包含一个这个结构体,可以看到该结构体中的成员都是一些函数指针,例如计算key hash值,key复制函数,value复制函数等。这样做的好处是,抽象。

/*
  * 字典类型特定函数
  */
 typedef struct dictType {
 
     // 计算哈希值的函数
     unsigned int (*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;


hash表结构体。table是hash表数组,一个二维数组,table[i]表示分配到第i个桶的所有hash表节点链接起来的链表;size表示hash表table的大小;sizemask=size-1是hash表掩码,用于计算索引值(节点索引值计算方式:计算key的hash_value,然后index=hash_value &sizemask);used表示hash表已有节点数量。

redis中定义的dict都包含两个这样的hash表,用以实现渐进式rehash。

/*
  * 哈希表
  *
  * 每个字典都使用两个哈希表,从而实现渐进式 rehash 。
  */
 typedef struct dictht {
 
     // 哈希表数组
     dictEntry **table;
 
     // 哈希表大小
     unsigned long size;
 
     // 哈希表大小掩码,用于计算索引值
     // 总是等于 size - 1
     unsigned long sizemask;
 
     // 该哈希表已有节点的数量
     unsigned long used;
 
 } dictht;

最后来看看dict结构

type是类型的特定函数集合;ht[2]表示两个hash表;privdata是私有数据;rehashidx是rehash索引;privdata;iterators;

/*
  * 字典
  */
 typedef struct dict {
 
     // 类型特定函数
     dictType *type;
 
     // 私有数据
     void *privdata;
 
     // 哈希表
     dictht ht[2];
     
     // rehash 索引
     // 当 rehash 不在进行时,值为 -1
     int rehashidx; /* rehashing not in progress if rehashidx == -1 */
     
     // 目前正在运行的安全迭代器的数量
     int iterators; /* number of iterators currently running */
     
 } dict;



接着看看dict提供的API,主要包括dict的创建、释放,以及插入、删除、查找、替换等操作。

dict创建释放:

 dict *dictCreate(dictType *type, void *privDataPtr);
 void dictRelease(dict *d);


dict的增删查改:

 int dictAdd(dict *d, void *key, void *val);
 dictEntry *dictAddRaw(dict *d, void *key);
 int dictReplace(dict *d, void *key, void *val);
 dictEntry *dictReplaceRaw(dict *d, void *key);
 int dictDelete(dict *d, const void *key);
 int dictDeleteNoFree(dict *d, const void *key);
 dictEntry * dictFind(dict *d, const void *key);
 void *dictFetchValue(dict *d, const void *key);
 dictEntry *dictGetRandomKey(dict *d);


dict的hash表扩大以及rehash
 int dictExpand(dict *d, unsigned long size); 
 int dictRehash(dict *d, int n);
 int dictRehashMilliseconds(dict *d, int ms);

dict迭代器相关
 dictIterator *dictGetIterator(dict *d);
 dictIterator *dictGetSafeIterator(dict *d);
 dictEntry *dictNext(dictIterator *iter);
 void dictReleaseIterator(dictIterator *iter);






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值