redis基础数据结构(四) 字典

redis的字典底层靠hash实现,代码在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;
内部包含一个key和一个key对应的value,还有一个next指针用于分离链接法解决冲突,hash控制结构:
typedef struct dictht {
    dictEntry **table;
    unsigned long size;
    unsigned long sizemask;
    unsigned long used;
} dictht;

二级指针table表示这是一个使用分离链接法的hash表,每个dict头中有两个这样的hash表,用于装填因子达到阈值时倍增hash空间,否则对于分布式系统,比如客户服务器体系,某个客户访问可能导致装填因子达到阈值,倍增hash表,这是一个很耗时和性能的工作,对于这个倒霉的客户很不友好,所以使用两个hash表用于解决这个问题,用空间换性能,但是只要调整hash大小就会有性能问题,所以redis提供开关控制是否允许调整hash表大小。其他字段,size是大小,是刚好比希望的size大的2的幂,sizemask就是size-1,由于size是2的幂,所以掩码是全f,used是使用的个数

dict头:

typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    unsigned long iterators; /* number of iterators currently running */
} dict;

dict底层使用siphash,是一种非加密hash算法,dict.c中提供的api:

_dictRest:将一个dictht头中的内容清零

dictCreate:创建一个dict结构

_dictInit:初始化一个dict

dictRisize:将hash表尽可能减小,会导致装填因子接近1

dictExpend:重建一个hash表的大小或者新建一个hash表,若新建,直接用ht[0]接管,否则用ht[1]接管,在rehashing过程中不能调用此函数,因为ht[1]正在被占用,重建后hash表的大小是比提供的size大的第一个2的幂

dictRehash:在ht[1]已经分配内存之后调用此函数,调用者提供n,此函数从ht[0]移动n个有内容的桶到ht[1],但是最多访问10 * n个桶

timeInMilliseconds:计算当前时间对应的毫秒

dictRehashMilliseconds:在ms之间内,每次从ht[0]到ht[1]搬移100个有元素的桶,到时间后终止

_dictRehashStep:判断是否有迭代器,若没有,从ht[0]搬移1个桶到ht[1]

dictadd:将提供的key和value做成一个节点加入hash表

dictAddRaw:添加一个元素,根据是否是rehashing过程,加到ht[0]或者ht[1]

dictReplace:提供key和value,若key已经存在,更新value,否则插入到dict中

dictAddOrFind:添加或查找一个节点,并将这个节点返回

dictGenericDelete:删除一个节点,可根据需要决定是否释放节点内存

dictDelete:是dictGenericDelete的包装,返回成功或失败

dictUnlink:是dictDelete的包装,不释放节点内存,将节点返回

dictFreeUnlinkedEntry:调用dictUnlink后,调用此函数将节点内存释放

_dictClear:删除整个ht,并初始化字段

dictRelease:调用_dictClear删除ht[0]和ht[1],然后删除dict

dictFind:根据提供的key在dict中查找元素

dictFetchValue:根据提供的key查找并返回其value

dictFingerprint:产生一个dict的64bit指纹,使用64bit整数哈希,用于不安全迭代器

dictGetIterator:创建一个不安全的迭代器

dictGetSafeIterator:创建一个安全的迭代器

dictNext:取一个迭代器的下一个节点

dictReleaseIterator:释放一个迭代器

dictGetRandomKey:返回dict中的一个随机节点,有两次随机,一次找非空桶,一次找桶中的元素

dictGetSomeKeys:返回dict中的若干随机节点,是不纯粹的随机,永远先在ht[0]中找,并且找到桶之后,取桶中所有节点

rev:将一个unsigned long二进制位反转

dictScan:遍历一个dict,使用反转二进制比特迭代算法,保证遍历完整的同时,将rehashing过程中的重复遍历降低到最少,从小表到大表,不会重复,从大表到小表,可能有重复

_dictExpandIfNeeded:若配置了允许扩张hash表,当装填因子达到1的时候,扩大到2倍,若设置了不允许扩张hash表,当装填因子达到5的时候,扩大到2倍

_dictNextPower:返回比给定unsigned long大的第一个2的幂

_dictKeyIndex:根据给定的hash索引查找一个key的空的格子,若key已经存在,返回-1,若在rehashing过程中,永远返回ht[1]中的空格子

dictEmpty:清空dict的ht[0],ht[1]和迭代器

dictEnableResize:设置允许扩张表

dictDisableResize:设置不允许扩张表

dictGetHash:是dictHashKey的包装,调用hash函数或者key的hash索引

dictFindEntryRefByPtrAndHash:根据hash索引和key,查找一个节点,这个函数不要使用,应该使用dictFind

猜你喜欢

转载自blog.csdn.net/kdb_viewer/article/details/80675636
今日推荐