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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Redis中的hashtable是一种数据结构,用于存储键值对。它是通过哈希表实现的,具体来说是使用了一种叫做拉链法的碰撞解决方法。哈希表中的每个桶都是一个链表,当发生碰撞时,新的键值对会被插入到对应桶的链表中。这样可以保证在哈希表中存储大量的键值对,并且在插入、查找和删除操作上具有较高的效率。Redishashtable使用了siphash算法来计算键的哈希值,这个算法能够提供良好的随机分布性,并且计算速度较快。此外,Redishashtable还支持扩容操作,当哈希表的负载因子达到一定阈值时,会自动进行扩容,以保证哈希表的性能。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [Redis 数据结构 hashtable](https://blog.csdn.net/MrBaymax/article/details/116562596)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Redis字典(hashtable)](https://blog.csdn.net/u010710458/article/details/80604740)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

gopher333

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

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

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

打赏作者

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

抵扣说明:

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

余额充值