typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry;
内部包含一个key和一个key对应的value,还有一个next指针用于分离链接法解决冲突,hash控制结构:
typedef struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
} dictht;
二级指针table表示这是一个使用分离链接法的hash表,每个dict头中有两个这样的hash表,用于装填因子达到阈值时倍增hash空间,否则对于分布式系统,比如客户服务器体系,某个客户访问可能导致装填因子达到阈值,倍增hash表,这是一个很耗时和性能的工作,对于这个倒霉的客户很不友好,所以使用两个hash表用于解决这个问题,用空间换性能,但是只要调整hash大小就会有性能问题,所以redis提供开关控制是否允许调整hash表大小。其他字段,size是大小,是刚好比希望的size大的2的幂,sizemask就是size-1,由于size是2的幂,所以掩码是全f,used是使用的个数
dict头:
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx; /* rehashing not in progress if rehashidx == -1 */
unsigned long iterators; /* number of iterators currently running */
} dict;
dict底层使用siphash,是一种非加密hash算法,dict.c中提供的api:
_dictRest:将一个dictht头中的内容清零
dictCreate:创建一个dict结构
_dictInit:初始化一个dict
dictRisize:将hash表尽可能减小,会导致装填因子接近1
dictExpend:重建一个hash表的大小或者新建一个hash表,若新建,直接用ht[0]接管,否则用ht[1]接管,在rehashing过程中不能调用此函数,因为ht[1]正在被占用,重建后hash表的大小是比提供的size大的第一个2的幂
dictRehash:在ht[1]已经分配内存之后调用此函数,调用者提供n,此函数从ht[0]移动n个有内容的桶到ht[1],但是最多访问10 * n个桶
timeInMilliseconds:计算当前时间对应的毫秒
dictRehashMilliseconds:在ms之间内,每次从ht[0]到ht[1]搬移100个有元素的桶,到时间后终止
_dictRehashStep:判断是否有迭代器,若没有,从ht[0]搬移1个桶到ht[1]
dictadd:将提供的key和value做成一个节点加入hash表
dictAddRaw:添加一个元素,根据是否是rehashing过程,加到ht[0]或者ht[1]
dictReplace:提供key和value,若key已经存在,更新value,否则插入到dict中
dictAddOrFind:添加或查找一个节点,并将这个节点返回
dictGenericDelete:删除一个节点,可根据需要决定是否释放节点内存
dictDelete:是dictGenericDelete的包装,返回成功或失败
dictUnlink:是dictDelete的包装,不释放节点内存,将节点返回
dictFreeUnlinkedEntry:调用dictUnlink后,调用此函数将节点内存释放
_dictClear:删除整个ht,并初始化字段
dictRelease:调用_dictClear删除ht[0]和ht[1],然后删除dict
dictFind:根据提供的key在dict中查找元素
dictFetchValue:根据提供的key查找并返回其value
dictFingerprint:产生一个dict的64bit指纹,使用64bit整数哈希,用于不安全迭代器
dictGetIterator:创建一个不安全的迭代器
dictGetSafeIterator:创建一个安全的迭代器
dictNext:取一个迭代器的下一个节点
dictReleaseIterator:释放一个迭代器
dictGetRandomKey:返回dict中的一个随机节点,有两次随机,一次找非空桶,一次找桶中的元素
dictGetSomeKeys:返回dict中的若干随机节点,是不纯粹的随机,永远先在ht[0]中找,并且找到桶之后,取桶中所有节点
rev:将一个unsigned long二进制位反转
dictScan:遍历一个dict,使用反转二进制比特迭代算法,保证遍历完整的同时,将rehashing过程中的重复遍历降低到最少,从小表到大表,不会重复,从大表到小表,可能有重复
_dictExpandIfNeeded:若配置了允许扩张hash表,当装填因子达到1的时候,扩大到2倍,若设置了不允许扩张hash表,当装填因子达到5的时候,扩大到2倍
_dictNextPower:返回比给定unsigned long大的第一个2的幂
_dictKeyIndex:根据给定的hash索引查找一个key的空的格子,若key已经存在,返回-1,若在rehashing过程中,永远返回ht[1]中的空格子
dictEmpty:清空dict的ht[0],ht[1]和迭代器
dictEnableResize:设置允许扩张表
dictDisableResize:设置不允许扩张表
dictGetHash:是dictHashKey的包装,调用hash函数或者key的hash索引
dictFindEntryRefByPtrAndHash:根据hash索引和key,查找一个节点,这个函数不要使用,应该使用dictFind