redis之dict

来源:互联网 发布:淘宝店铺层级的排名 编辑:程序博客网 时间:2024/04/30 09:51

redis的dict是自动rehash的hash表,为了平衡性能,rehash不是一次做完的,而是分散到每次交互操作来做;

typedef struct dictEntry {
    void *key;
    void *val;
    struct dictEntry *next;
} dictEntry;

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;

/* This is our hash table structure. Every dictionary has two of this as we
 * implement incremental rehashing, for the old to the new table. */
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];
    int rehashidx; /* rehashing not in progress if rehashidx == -1 */
    int iterators; /* number of iterators currently running */

} dict;

dict包含两个hash表,当rehash时,逐步将ht[0]中元素挪至ht[1],全部挪完后,ht[0]=ht[1],结束rehash;

int dictRehash(dict *d, int n)

将ht[0]的n个非空桶的元素rehash到ht[1],更新rehashidx;

如果所有元素都已经rehash,则ht[0]=ht[1],reset(ht[1]),设置rehashidx为-1;

触发_dictRehashStep(在没有iterator的时候,挪元素)的操作有:dictAdd、dictReplace、dictGenericDelete、dictDelete、dictDeleteNoFree、dictFind;

dict *dictCreate(dictType *type, void *privDataPtr); // 创建dict

int dictExpand(dict *d, unsigned long size); // 当ht[0].table为NULL时,创建hashtable;其他时候,创建ht[1],设置rehashidx为0,开始rehash;

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

判断是否需要rehash,触发条件为:元素个数大于或等于桶个数且设置了可以rehash,或者元素个数是桶个数的5倍以上;

从ht[0]中查询是否有key存在,如果在rehash过程中,另需判断key是否在ht[1]中存在,如果存在,则添加失败;

如果在rehash过程中,将元素添加到ht[1],否则,添加到ht[0];

int dictReplace(dict *d, void *key, void *val);

先调用dictAdd,如果成功,直接返回;

失败则表明,key已经存在,调用dictFind获得dictEntry,将dictEntry->val替换掉;

static int dictGenericDelete(dict *d, const void *key, int nofree);

先尝试从ht[0]中删除key元素;

若ht[0]中没有key元素且在rehash过程中,则尝试从ht[1]中删除元素key;

void dictRelease(dict *d); // 释放dict

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

先从ht[0]找key,找到直接返回;

若ht[0]中没找到key元素且在rehash过程中,则尝试从ht[1]中找key;

dictIterator *dictGetSafeIterator(dict *d); // 创建迭代器

dictEntry *dictNext(dictIterator *iter); // 迭代元素

与普通hash表迭代器区别在于,如果dict处于rehash过程中,迭代完ht[0]后,会继续迭代ht[1];

在有迭代器迭代dict时,是不允许从ht[0]挪元素到ht[1]的;

dictEntry *dictGetRandomKey(dict *d);

从dict中随机获取一个元素;

原创粉丝点击