redis源码阅读笔记 字典
字典是redis中实现的一种数据结构,其中一些api函数的相互调用关系有一点复杂,故做一篇记录整理一下。
常用api
- dictCreate 创建新的字典
- dictAdd 向字典中插入给定键值
- dictReplace 同上,如果存在则替换
- dictFetchValue 返回给定键的值
- dictGetRandomKey 从字典中随机返回一个键值对
- dictDelete 从字典中删除给定键所对应的键值对
- dictRelease 释放给定字典及其所包含的键值对
函数调用分析
dictCreate
-
zmalloc 分配内存
-
_dictInit 初始化
-
_dictReset 设置相关变量
dictAdd
- dictAddRaw 尝试添加键到字典,并返回包含了这个键的新哈希节点
- _dictRehasgStep 如果条件允许,进行单步rehash
- dictRehash
- 如果0号哈希表为空,表示rehash执行完毕,则释放0号哈希表,将1号哈希表设置为新的0号哈希表,_dictReset重置旧的1号哈希表,关闭rehashidx标识
- 否则找到0号哈希表中第一个非空索引,循环遍历其中所有的值,计算在新哈希表中的索引,将其插入,更新计数器,置刚迁移完的哈希表索引指正为空,更新rehashidx标识
- dictRehash
- _dictKeyIndex 计算键在哈希表中的索引值,如果键已经存在,则返回NULL
- _dictExpandIfNeeded 如果需要的话扩展哈希表
- 如果正在进行rehash则直接返回
- dictExpand 如果0号哈希表为空,则常见并返回初始化大小(size=4)的0号哈希表
- 如果正在进行rehash则直接返回,或者size小于0号哈希表当前使用的节点(说明这个时候0号哈希表不是空的)也返回
- _dictNextPower 根据size计算新的哈希表大小
- 初始化操作,zcalloc创建空间
- 如何0号哈希表为空,那么这是一次初始化,新哈希表赋给0号哈希表,程序可以开始处理键值对。
- 如果0号哈希表不为空,那么这是一次rehash,新哈希表赋给1号哈希表,打开rehashidx标识,程序可以开始进行rehash
- dictExpand 如果节点数和字典大小比例不满足条件,则扩展哈希表
- 计算key的哈希值,如果字典正在rehash,则计算其在1号哈希表中的索引,否则计算其在0号哈希表中的索引。如果键在哈希表中存在,则返回-1,否则返回其对应的索引
- _dictExpandIfNeeded 如果需要的话扩展哈希表
- 如果字典正在rehash,新键添加到1号哈希表,否则添加到0号哈希表
- _dictRehasgStep 如果条件允许,进行单步rehash
- 键已存在则添加失败,否则设置节点的值,添加成功
dictReplace
-
dictAdd key不存在的话,添加成功
-
dictFind key已存在,则查找包含这个key的节点
-
设置新值,释放旧值
其他api都很简单,主要是add操作比较麻烦