dict 是redis中最重要的数据结构,存放结构体redisDb中。

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

其中type是特定结构的处理函数

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;

privdata就是上述函数的参量,dict中定义了两个哈希表dictht,作为rehash使用,一开始加入的键值对放入ht[0]中,它像普通的hash表一样使用链表法来避免冲突,当ht中的加入的数据个数超过他的容量,就开始rehash,将数据转移到容量更大的ht[1]中,rehash的过程并不是上来就把整个ht[0]一次性的放到ht[1]中,它使用的是渐进式的转移。

渐进式rehash 主要由_dictRehashStep 和dictRehashMilliseconds 两个函数进行:
• _dictRehashStep 用于对数据库字典、以及哈希键的字典进行被动rehash ;
• dictRehashMilliseconds 则由Redis 服务器常规任务程序(server cron job)执行,用于对数据库字典进行主动rehash ;

主要操作在dictRehash中进行。

/* Performs N steps of incremental rehashing. Returns 1 if there are still
* keys to move from the old to the new hash table, otherwise 0 is returned.
* Note that a rehashing step consists in moving a bucket (that may have more
* than one key as we use chaining) from the old to the new hash table. */
int dictRehash(dict *d, int n) {
if (!dictIsRehashing(d)) return ; while(n--) {
dictEntry *de, *nextde; /* Check if we already rehashed the whole table... */
if (d->ht[].used == ) {
zfree(d->ht[].table);
d->ht[] = d->ht[];
_dictReset(&d->ht[]);
d->rehashidx = -;
return ;
} /* Note that rehashidx can't overflow as we are sure there are more
* elements because ht[0].used != 0 */
assert(d->ht[].size > (unsigned)d->rehashidx);
while(d->ht[].table[d->rehashidx] == NULL) d->rehashidx++;
de = d->ht[].table[d->rehashidx];
/* Move all the keys in this bucket from the old to the new hash HT */
while(de) {
unsigned int h; nextde = de->next;
/* Get the index in the new hash table */
h = dictHashKey(d, de->key) & d->ht[].sizemask;
de->next = d->ht[].table[h];
d->ht[].table[h] = de;
d->ht[].used--;
d->ht[].used++;
de = nextde;
}
d->ht[].table[d->rehashidx] = NULL;
d->rehashidx++;
}
return ;
}

dict中的iterators有两种,安全迭代器和不安全迭代器。这相当于c++中的const_iterator和iterator。用来遍历字典中的数据,即dictEntry。

typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
} v;
struct dictEntry *next;
} dictEntry;

dictEntry可以看做是链表的节点,存放于dictht->table中。如果发生key的哈希值碰撞,则在将发生碰撞的key插入到next上形成链表结构。上面讲的rehash操作就是为了避免链表过长,增加bucket的容量。

redis源码解析之dict数据结构的更多相关文章

  1. [Redis源码阅读]dict字典的实现

    dict的用途 dict是一种用于保存键值对的抽象数据结构,在redis中使用非常广泛,比如数据库.哈希结构的底层. 当执行下面这个命令: > set msg "hello" ...

  2. Redis源码解析之跳跃表(三)

    我们再来学习如何从跳跃表中查询数据,跳跃表本质上是一个链表,但它允许我们像数组一样定位某个索引区间内的节点,并且与数组不同的是,跳跃表允许我们将头节点L0层的前驱节点(即跳跃表分值最小的节点)zsl- ...

  3. Redis源码分析(dict)

    源码版本:redis-4.0.1 源码位置: dict.h:dictEntry.dictht.dict等数据结构定义. dict.c:创建.插入.查找等功能实现. 一.dict 简介 dict (di ...

  4. .Net Core缓存组件(Redis)源码解析

    上一篇文章已经介绍了MemoryCache,MemoryCache存储的数据类型是Object,也说了Redis支持五中数据类型的存储,但是微软的Redis缓存组件只实现了Hash类型的存储.在分析源 ...

  5. Redis源码解析:15Resis主从复制之从节点流程

    Redis的主从复制功能,可以实现Redis实例的高可用,避免单个Redis 服务器的单点故障,并且可以实现负载均衡. 一:主从复制过程 Redis的复制功能分为同步(sync)和命令传播(comma ...

  6. Redis源码解析:13Redis中的事件驱动机制

    Redis中,处理网络IO时,采用的是事件驱动机制.但它没有使用libevent或者libev这样的库,而是自己实现了一个非常简单明了的事件驱动库ae_event,主要代码仅仅400行左右. 没有选择 ...

  7. Redis源码解析:25集群(一)握手、心跳消息以及下线检测

    Redis集群是Redis提供的分布式数据库方案,通过分片来进行数据共享,并提供复制和故障转移功能. 一:初始化 1:数据结构 在源码中,通过server.cluster记录整个集群当前的状态,比如集 ...

  8. Redis源码解析

    一.src/server.c 中的redisCommandTable列出的所有redis支持的命令,其中字符串命令包括从get到mget:列表命令从rpush到rpoplpush:集合命令包括从sad ...

  9. Redis源码解析:26集群(二)键的分配与迁移

    Redis集群通过分片的方式来保存数据库中的键值对:一个集群中,每个键都通过哈希函数映射到一个槽位,整个集群共分16384个槽位,集群中每个主节点负责其中的一部分槽位. 当数据库中的16384个槽位都 ...

随机推荐

  1. hasOwnProperty()方法与in操作符

    1.hasOwnProperty() 该方法检测属性存在于实例,还是存在于原型,对于存在于实例中的属性则返回true 2.in 使用该操作符时只要通过对象能够访问到的属性都会返回true

  2. Python模块学习 - click

    Click模块 click模块是Flask的作者开发的一个第三方模块,用于快速创建命令行.它的作用与Python标准库的argparse相同,但是,使用起来更简单. click是一个第三方库,因此使用 ...

  3. wait与waitpid

    1. 函数原型: #include <sys/wait.h> pid_t wait(int *statloc); pid_t waitpid(pid_t pid, int *statloc ...

  4. 在 Visual Studio 中使用正则表达式

    Visual Studio 使用 .NET framework 正则表达式查找和替换文本. 在 Visual Studio 2010 和早期版本中,Visual Studio 在“查找和替换”窗口中使 ...

  5. [ python ] 类的组合

    首先,使用面向对象是一个人狗大战的实例: class Person: def __init__(self, name, hp, aggr, sex): self.name = name self.hp ...

  6. [ Python ] 基本数据类型及属性(下篇)

    1. 基本数据类型 (1) list 列表     (2) tuple 元组     (3) dict 字典     (4) set 集合 2. list 列表方法 Python 内置的一种数据类型, ...

  7. linux命令(25):ln命令

    命令格式: ln [参数][源文件或目录][目标文件或目录] 必要参数: -b 删除,覆盖以前建立的链接 -d 允许超级用户制作目录的硬链接 -f 强制执行 -i 交互模式,文件存在则提示用户是否覆盖 ...

  8. Search Insert Position——二分法

    Given a sorted array and a target value, return the index if the target is found. If not, return the ...

  9. 深度理解onmouseover事件和onmouseout事件

    今天简单的讲解下onmouseover事件和onmouseout事件,一直以为它们只是简单的分别实现鼠标指针移动到元素上时触发事件和在鼠标指针移出指定的对象时触发事件,但是突然发现这些只是对它们简单的 ...

  10. Python基础系列----函数,面向对象,异常

    1.前言                                                                                               前 ...