redis--内部结构--dict

来源:互联网 发布:360手机数据恢复 编辑:程序博客网 时间:2024/05/18 01:41

字典又称符号表、关联数组或映射,是一种用于保存键值对的抽象数据结构;
redis的数据库就是使用字典来作为底层实现的,对数据库的增、删、改、查都是构建在对字典的操作之上的;

字典的实现

1、哈希表
redis字典所使用的哈希表有dict/dictht结构定义;

typedef struct dictht{    dictEntry **table;//哈希表数组    unsigned long size;//哈希表大小    unsigned long sizemask;//哈希表大小掩码    unsigned long used;//哈希表已有节点数量}dictht;
哈希表节点:typedef strcut dictEntry{    void *key;//键    union{        void *val;        uint64_t u64;        int64_t s64;    }v;//值    strcut dictEntry *next;}dictEntry;
字典:typedef struct dict{    dictType *type;//类型特定函数    void *privdata;//私有数据    dictht ht[2];//哈希表    int trehashidx;//记录rehash进度,如果目前没有在进行rehash,那么它的值为-1;}dict;

这里写图片描述

2、哈希算法
使用字典设置的哈希函数,计算key的哈希值;
hash = dict->type->hashFunction(key);
使用哈希表中的sizemask属性和哈希值,计算出索引值;
index= hash & dict->ht[x].sizemask;
3、解决键冲突
Redis的哈希表采用链地址法来解决键冲突;每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表,当插入新的哈希节点时,总是使用头插法
4、rehash
随着操作的不断执行,哈希表保存的键值对会逐渐地增多或者减少,为了让哈希表的负载因子维持在一个合理的范围之内,当哈希表保存的键值对数量太多或者太少,程序需要对哈希表的大小进行相应的扩展或者收缩;
扩展和收缩的工作可以通过执行rehash操作来完成;
<1>位字典ht[1]分配空间,大小取决于要执行的工作;
<2>将保存在ht[0]中的所有键值对rehash到ht[1]中,rehash指的是重新计算键的哈希值和索引值;
<3>当ht[0]中的所有节点都迁移到了ht[1]中,就将ht[1]变为ht[0],将ht[1]新创建一个空白的哈希表;
5、渐进式rehash
扩展和收缩是将ht[0]中的所有键值对rehash到ht[1]中,但是这个动作,对于4个来说很快,如果键值对的个数达到4亿多个,庞大的计算量可能会导致服务器在一段时间没停止服务;为了避免rehash对服务器性能造成的影响,服务器不是一次性将ht[0]里面的所有键值对全部rehash到ht[1]中,而是分多次,渐进式地将ht[0]里面的键值对慢慢地rehash到ht[1]中;渐进式的好处在于它采用了分而治之的方式;
另外,在渐进式rehash执行期间,新添加到字典的键值对一律会被保存到ht[1]里面,而ht[0]则不再进行任何添加操作,这一措施保证了ht[0]包含的键值对数量只减不增;

引用来自《Redis设计与实现》

原创粉丝点击