redis--字典

字典

字典,又称关联数组或映射,是一种用于保存键值对的抽象数据结构。在字典中,一个键key和一个值value进行关联;字典中的每个键都是独一无二的。

字典的实现

redis的字典使用哈希表作为底层实现,一个哈希表可以有很多节点,而每个节点就保存了字典中的一个键值对。

哈希表

定义结构如下:

typedef struct dictht {
    //哈希表数组
    dictEntry **table;
    //哈希表大小
    unsigned long size;
    //哈希表大小掩码,用于计算索引值
    unsigned long sizemask
    //该哈希表已有的节点数量
    unsigned long used;
}dictht;

结构示意图如下:


哈希表
哈希表节点

哈希表节点使用dictEntry结构表示,每个节点都保存着一个键值对:

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

结构图如下:

哈希表
字典

redis中的字典结构如下:

typedef struct dict {
    //类型特定函数
    dictType *type;
   //私有数据
   void *privdata;
   //哈希表
   dictht ht[2];
   //rehash索引,不进行rehash时,值为-1
   int trehashidx;
}
  • [ ] type属性是一个指向dictType结构的指针,每个dictType保存了一组用于操作特定类型键值对的函数,redis会为用途不同的字典设置不同类型特定函数。
  • [ ] privdata属性,则保存了需要传递给那些类型特定函数的可选参数。
typedef struct dicType {
    //计算哈希值得函数
    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)
    //销毁键的函数
    int (*keyDestructor) (void *privdata,void *key);
    //销毁值得函数
    void (*valDestructor) (void *privdata,void *obj);
}

普通状态下的字典如图所示:

字典结构

ht是包含两个项的数组,每个项都是一个哈希表,字典只用ht[0]哈希表,ht[1]哈希表只会在对ht[0]哈希表进行rehash时使用。当两个及以上的键值对分配到了哈希数组中的同一个索引上,成为冲突,通过单链表的形式解决

哈希算法

当要将一个新的键值对添加到字典里时,程序需要先根据键值对的键计算出哈希值和索引值,然后再根据索引值,将包含新键值对的哈希表节点放到哈希表数组的指定索引上面。

redis使用MurmurHah2算法来计算哈希值。

新节点总是在已有节点的前边。

rehash

随着操作的不断执行,哈希表的键值对会增加或者减少,为了让负载因子维持在合理的范围内,哈希表需要扩展或者收缩。

步骤如下:

  1. 为字典的ht[1]哈希表分配空间,这个空间取决于要执行的操作,以及ht[0]当前包含的键值对数量。
  • 如果是执行扩展操作,那么ht[1]的大小为:
ht [0].used*2^{n} + 1
  • 如果执行的是收缩操作,那么ht[1]的大小为:
ht [0].used*2^{n}
  1. 将保存在ht[0]中ed所有键值对rehash到ht[1]中,rehash指的是重新计算哈希值和索引,然后将键值对放到哈希表指定的位置上。
  2. 当ht[0]迁移完之后,释放ht[0],将ht[1]的值设为ht[0],并在ht[1]上创建一个空的哈希表,为下一次rehash做准备。
渐进式rehash

rehash操作不是一次性,集中式的完成,而是分多次渐进式的完成的。在rehash期间,每对字典的添加,删除,查找或者更新操作时,都会进行rehash操作;在渐进式rehash期间,新添加的键值对一律会添加到ht[1]中,而不对ht[0]进行操作。

字典api
函数 作用 时间复杂度
dictCreate 创建一个新的字典 O(1)
dictAdd 将给定的键值对添加到字典中 O(1)
dictReplace 将给定的键值对添加到字典中,如果已经存在,那么用新的值取代原有的值。 O(1)
dictFetchValue 返回给定键的值 O(1)
dictGetRandomKey 从字典中随机返回一个键值对 O(1)
dictDelete 从字典中删除给定键所对应的键值对 O(1)
dictRelease 释放给定字典,以及字典中包含的所有键值对 O(N) N为字典包含的键值对数量
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 本文摘抄自redis阅读笔记 典在Redis中应用十分广泛,它是实现数据库的基础,特别的它是数据库键空间的实现方式...
    lintong阅读 596评论 0 3
  • 字典的实现 hash表结构 table 属性是一个数组, 数组中的每个元素都是一个指向 dict.h/dictEn...
    来年花惜阅读 650评论 0 0
  • 字典 Redis 中的字典 由 dict.h/dict 结构表示: type 和 privdata 是针对不同类型...
    jiangmo阅读 529评论 2 0
  • 字典,又称为符号表(symbol table)、关联数组(associative array)或映射(map),是...
    我要尝鲜阅读 229评论 0 1
  • 哈希表 其中主要是table用于存放数据,其是一个dictEntry指针数组 哈希表节点 字典的实现 其中的typ...
    Chasiny阅读 330评论 0 0