1. Redis中的字典
Redis中的字典(也叫哈希表)是一个无序键值对集合,其中的键都是唯一的。字典使用哈希表来实现,哈希表是一个数组,数组中的每个元素又是一个链表,链表中存储了键值对。获取键的值时,只需要先对键进行哈希,然后在哈希表中查找就行了。在Redis中,字典类型被广泛应用于各种场景中,比如存储用户信息、统计网站访问次数等。
1.1 字典的实现
字典使用哈希表实现,哈希表是一个数组,数组中的每个元素又是一个链表,链表中存储了键值对。哈希表的大小一般会预分配一些空间,如果哈希表中的元素数量增加到一定程度,就会进行扩容。扩容的过程是比较耗费时间和空间的,因此,预分配空间的大小一般需要根据实际情况来调整。
typedef struct dictht {
dictEntry **table; // 指向哈希表数组
unsigned long size; // 哈希表数组的大小
unsigned long sizemask; // 哈希表数组大小掩码,用于计算索引值
unsigned long used; // 哈希表已使用节点数量
} dictht;
1.2 字典的操作
Redis中对字典的操作有:
添加键值对
删除键值对
查找键值对
修改键值对
2. Redis中的哈希算法
哈希算法是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。在Redis中,哈希算法被广泛应用于字典中的键的计算。
2.1 哈希算法的种类
Redis中可以使用的哈希算法有:
MurmurHash2
CRC64
MD5
SHA1
xxHash
2.2 MurmurHash2算法
MurmurHash2算法是非常快速、有效、分布均衡的哈希算法,是Redis中的默认哈希算法。它的特点是:
速度快
碰撞较少
分布均匀
uint32_t MurmurHash2(const void *key, int len, uint32_t seed) {
const uint32_t m = 0x5bd1e995;
const int r = 24;
const unsigned char *data = (const unsigned char *) key;
uint32_t h = seed ^ len;
while (len >= 4) {
uint32_t k = *(uint32_t*) data;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
switch (len) {
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
}
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
2.3 哈希算法的应用
在Redis中,哈希算法被广泛应用于字典中的键的计算。当我们需要在字典中查找某个键的值时,可以先计算出该键的哈希值,然后在哈希表中查找对应的节点。
3. Redis中的ReHash原理
3.1 ReHash概述
Redis中的哈希表使用了拉链法来解决哈希冲突。当哈希表中的元素数量增加到一定程度,就会进行ReHash操作,即扩容。ReHash操作是比较耗费时间和空间的,因此,预分配空间的大小一般需要根据实际情况来调整。
3.2 ReHash的原理
ReHash的原理是:
创建一个新的哈希表
将旧哈希表中的元素逐个复制到新哈希表中
完成复制后,将新哈希表替换旧哈希表
3.3 ReHash的时间复杂度
ReHash的时间复杂度是O(N),其中N是哈希表中元素的数量。在ReHash操作过程中,需要对每个元素进行哈希计算和元素移动操作。因此,ReHash的时间复杂度是与哈希表中元素的数量线性相关的。
3.4 如何减少ReHash的次数
可以采取以下措施来减少ReHash的次数:
预分配空间
扩容因子
3.4 预分配空间
预分配空间是指在创建哈希表时,就提前分配好一定的空间,以避免频繁的扩容操作。预分配空间的大小需要根据实际情况来调整。
3.5 扩容因子
扩容因子是指当哈希表中的元素数量达到一定程度时,就会进行扩容操作。一般情况下,扩容因子的大小为2,即当哈希表中的元素数量超过2倍的哈希表大小时,就会进行扩容操作。可以通过修改扩容因子来调整ReHash的次数。
结语
Redis中的字典、哈希算法和ReHash原理是Redis中非常重要的基础知识。了解这些内容对于理解Redis的使用和原理有着至关重要的作用,希望本篇文章能对大家有所帮助。