这是我参加更文应战的第2天,活动概况检查: 更文应战

概述:

在redis中有许多当地都用到了字典结构,比方咱们redis中的哈希结构便是用的字典结束的,而字典结构的底层事运用哈希表结束的(有点绕~),XDM能够经过这篇文章了解到以下知识点。

  1. 哈希表源码之家、哈希表节点、以及字典的结构和结束。

  2. 哈希算数组的界说法redis是怎样处理哈希抵触的。

  3. redi数组的界说s的rehash原理和结束

哈希表、哈希表节点、以及字典的结构和结束

哈希表

哈希表的结构是这个姿态的:源码编辑器编程猫

typedef struct线程 dictht {
// 哈希表数组
dictEntry **table;(这个是指向指针的指针)
// 哈希表巨细
unsigned long size;
// 哈希表巨细掩码,用于核算索引值
// 总是等于 size - 1
unsigned long sizemask;
// 该哈希表已有节点的数量
unsign源码编辑器编程猫下载ed long used;
} dictht;

tab数组公式le是一个指针数组,他里面的每个元素都指向一个哈希表节点dictEntry。

size 是当时哈希表的巨细,也便是咱们table数组中元素数

used记录了哈希表现在已有节点(源码时代键值对)的数量

sizemask 特色的值总是等于size – 1 , 这个特色和哈希值一起决议一个键应该被放到数组的哪个索引上面。这个假设没有记错的话应该是用来数组的界说rehash运用的。源码编辑器编程猫下载

哈希表节点

type线程池的七个参数def struct dictEntry {
// 键
void *key;
// 值
union {
void *val;
uint64_t u6服务器4;
int64_t s64;
} v;
// 指向下个哈希表节点,数组公式构成链表
struct dictEntry *next;
} dictEntry;

key便是咱们哈希源码分享网的key,指向了一个SDS目标或许是一个整数。

next是一个指针指向一个dictEntry目标,这个是为了处理哈希抵触的,当哈希抵触发生的时分,一数组词切抵触的key的就会构成一条链线程安全表。

redis字典结构结束篇你确认不看吗?

字典

typedef struct dict {
// 类型特定函数
dictType *type;
// 私有数数组据
void *privdata数组的界说;
// 哈希表
dictht ht[2];
// rehash 索引
// 当 rehash 不在进行时,值为 -1
int rehashid线程池的七个参数x; /* rehashing not in progress if rehashidx == -1 */
} dict;

type 是一个指向dictType结构的指针,每个dictType中都包含了操作不同类型字符串的办法,privdata则保存了这些办法需求的参数

dic线程池创立的四种tType的结构如下:

typedef struct dictType {
// 核算哈希值的函数
unsigned int (*hashFunction)线程池面试题(cons源码之家t void *key);
//服务器升级中是什么意思 复制键的函数
void *(*keyDup)(void *privdata, const void *key);
// 复制值的函数
void *(*valDup)(void *privdata, const void *obj);
// 比照键的函数
int (*keyCompare)(源码编辑器编程猫void *privdata, const voi数组长度d *key1, const void *key2);
// 毁掉键的函数
void (*keyD线程和进程的差异是什么estructor)(void *pr服务器升级中是什么意思ivdata, void *key);
// 毁掉值的函数
void (*valDestructor)(void *privdata, v源码oid *obj);
} dic源码之家tType服务器升级中是什么意思;

咱们能够看到还有两个字段 ht[2]和rehashidx,正常情况下咱们的数据线程池都是在ht[0]中的。那ht[1]只要在rehash的时分才会运用,而rehashidx便是咱们的rehash开展,当rehashidx为-1的时分就阐明当时哈希表没有进行rerediscoveringhash操作。在redis源码中咱们能够看到这种判别。

这是一数组c语言个没有进行rehash的一般字典结构:redis字典结构结束篇你确认不看吗?

线程希算法redis是怎样处理哈希抵触的

当两个或许多个的key经过哈希算法算出来的值是相同线程的几种状况的时分咱们就称这种是呈现了哈希抵触,在上边介绍根本结构的时分就提到过这个next是一个指针指向一个dictEntry目标,当哈希抵触发生的时分,一切抵触的key的就会构成一条链表。当查询的时分就会依照这个链表一个一个往后服务器查找到和需求获取的key相等的值,然后回服务器是什么来。

redisredis应用场景的rehash原理和结束

负载因子

首要咱们要先介绍一下负载因子的概念,在咱们对哈希表的增加和线程删去操作的进程中会导致咱们的哈希表不断增大。从而导致ht[0].used / ht[0].size 比例失衡 这两个的概念需求看下上边数组的界说的界说。

咱们能够想一下这比例在什么时分这个哈希表是最优状况?

应该是1,由于假设是1空间没有糟蹋,也阐明没有那么多的哈希抵触。

redis会根据这个份线程和进程的差异是什么额判别咱们哈希表是要扩服务器租借多少钱一年展仍是缩短。接下数组指针来咱们大约看一下这个rehash的进程。

  1. 这第一步就要运用到咱们的ht[1数组词],先为它分配空间。详细分配多大的空间要取决于咱们是要实施扩展仍是缩短操作,还有便是当时ht服务器和电脑主机的差异[0]中的元素数量。(扩展操服务器怎样搭建作ht[1]的巨细是第一个大于等于hredis耐久化t[0].used * 2^n 假设是缩短操作巨细为第一个大于等于ht[0].used的2^n。 这个咱们解释一下,比方当时咱们的used是6,rediscover咱们需求请求的空间便是(6*2 = 12)数组词<2^4是16。应该都能够了解哈~)。
  2. 然后便是将咱们ht[0]上的key运用新的从头核算哈希值和索引值,并依照新的索引值放到咱们的ht[1]上。线程池的七个参数
  3. 当咱们的ht[0]上的一切键值对都迁移到ht[1]之后ht[0]是空表了,此时将ht[0]指向ht[1] ht[1]redis岗兵形式指向null服务器租借多少钱一年 至此咱们的rehash就结束了。

什么时分会进行服务器地址在哪里看rehash呢?

  1. 服务器现在没有在实施 BGSAVE 指令或许 BGREWRITEAOredis面试题F 指令, 并且哈希表的负载因子大于等于1进行扩展操作。

  2. 服务器正在数组长度实施 BGSAVE 指令或许 BGREWRITredis数据结构EAOF 指令, 并且哈希表的负载因子大于等于5进行扩展操作。

  3. 当哈希表的负数组载因子小于0.1时, 程序自动开端对哈希表实施缩短操作

详细为什么服务器是什么 BGSAVE 指令或许源码编辑器编程猫下载 BGREWRITEAOF 指令实施期间负载因子的判别值不相同,我猜想是由于功用的考虑,xdm能够查一下相关材料议论下

咱们上边说的rehash并不是一下就悉数结束,假设咱们有个很大的哈源码资本希表那reha线程撕裂者sh进程是要消耗很长时间的咱们的redis是单线程,这种消源码编辑器手机版下载耗主线程时间的逻辑很丧身的。redis在这个当地的规划真的是很高雅,xdm肯定发现咱们还有一个reh源码资本ashidx字段没用到,字段便是咱们后边要写的渐进式rehash中要运用到的重要内容。

总结

xdm这篇先到这,首要拾掇了下redis字典底层哈希表数组长度的结束,以及rehash的进程。接下来会拾掇一下redis的高雅规划渐进式rehash和他的源码结束。

敬请期待~