Redis之字典(hashtable)

字典是什么(hashtable)

简单来说就是Redis中hash数据结构的底层实现
当数据小, 并且数量不多的时候会用ziplist来实现hash结构

总体结构

这里先给出大体的结构, 便于理解
在这里插入图片描述

dict

字典底层又是由dict实现的, 下图是dict的结构
在这里插入图片描述

typedef struct dict{
         //类型特定函数
         void *type;
         //私有数据
         void *privdata;
         //哈希表(散列表)
         dictht ht[2];
         //rehash 索引 当rehash不在进行时 值为-1
         int trehashidx; 
}dict;

dictht[]数组长度为2, 一般我们使用dictht[0], 另外一个dictht[1]作为rehash使用

dictht(散列表)

接下来我们看一下dictht(散列表的实现)

typedef struct dictht
{
         //哈希表数组
         dictEntry **table;
         //哈希表大小
         unsigned long size;
         //哈希表大小掩码,用于计算索引值
         unsigned long sizemask;
         //该哈希已有节点的数量
         unsigned long used;
}dictht;

dictEntry

  • dictEntry是一个散列表节点
    散列表的节点是由下定义的
//哈希表节点定义dictEntry结构表示,每个dictEntry结构都保存着一个键值对。
typedef struct dictEntry
{
         //键
         void *key;
         //值
         union{
           void *val;
            uint64_tu64;
            int64_ts64;
            }v;
         // 指向下个哈希表节点,形成链表
         struct dictEntry *next;
}dictEntry;
  • key就是实际存储键的地方
  • 联合体中就是实际存储值的地方
  • 散列表节点还有一个next域指向下一个节点, 可以用来解决哈希冲突问题

如何解决哈希冲突

1. 链表法

当有两个或以上的键被分配到散列表数组同一个索引上时,就发生了键冲突。Redis使用链表法解决散列冲突。
值得一提的是比如V0先加入这个节点中, 又来一个V1和V0的值一个都被分配 到了一个地址, 那么就会在V0的头部插入V1.
在这里插入图片描述

2.rehash法

随着操作的进行, dict内保存的键值对,会不断的减少或者增加, 我们需要保证负载因子的正常, 那么就要重新进行分配内存
这个时候dicht[1]就可以起到作用了, 并且rehashids也会设置为0表示正在rehash中
在这里插入图片描述
rehash的过程
1.为字典的ht[1]散列表分配空间,这个空间的大小取决于要执行的操作以及ht[0]当前包含的键值对数量(即:ht[0].used的属性值)

  • 扩展操作:ht[1]的大小为 第一个大于等于ht[0].used2的2的n次方幂。如:ht[0].used=3则ht[0] = 32 = 6, 第一个大于或者等于的2^n就是 2 ^ 3=8所以ht[1]的大小为8,ht[0].used=4则ht[1]的大小也为8。
  • 收缩操作: ht[1]的大小为 第一个大于等于ht[0].used的2的n次方幂。

2.将保存在ht[0]中的键值对重新计算键的散列值和索引值,然后放到ht[1]指定的位置上. 当然这不是一步完成的, 是一部分一部分的赋值过去
3.当我们把ht[0]上面所有的键值对都给移过去到h[1]之后, 就会释放h[0]的空间, 并且将h[1]记为ht[0], 最后再创建一个新的ht[1]散列表为下一次rehash做准备。

这就是本次全部内容,若是看不懂建立配合着图来理解

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gopher333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值