Redis的数据类型(一)dict篇

reids是什么就不过多描述了,咱直接进入主题

我们都知道redis的5大数据类型:string,list,hash,set与zset。但其实就redis而言,它的整体是一个dict类型的,是redis中所有key到value的映射。

一、dict

下面写到:每个字典都有两个这样的对旧表到新表执行增量重新散列。

/* This is our hash table structure. Every dictionary has two of this as we
 * implement incremental rehashing, for the old to the new table. */
typedef struct dict {
    dictType *type;    //dictType结构中包含自定义的函数,这些函数使得key和value能够存储任何类型的数据
    void *privdata;    //私有数据,保存着dictType结构中函数
    dictht ht[2];      //两张哈希表
    long rehashidx;    //rehash的标记,rehashidx == -1,表示没有进行 rehash
    int16_t pauserehash;    //正在迭代的迭代器数量
} dict;
typedef struct dictht {
    dictEntry **table;        //存放一个数组的地址,数组中存放哈希节点dictEntry的地址
    unsigned long size;       //哈希表table的大小,出始大小为4
    unsigned long sizemask;   //用于将hash值映射到table位置的索引,大小为(size-1)
    unsigned long used;       //记录哈希表已有节点(键值对)的数量
} dictht;

既然是hash,那么就一定会有扩容的操作。看看具体是怎么做的

这里着重说一下两张哈希表,先说结论,dict数据与java中的map相似,主要是根据负载因子(源码中的参数load_factor)进行扩容的操作。

  1. 负载因子
    1. load_factor = ht[0].used / ht[0].size,这是计算负载因子的公式
    2. 在正常情况下,当 load_factor 大于1时,会进行扩容操作
    3. 在RDB/AOF(做持久化,可以理解为mysql的binlog)阶段,load_factor 默认大于5才会进行扩容操作。
      1. redis会fork一个子进程,在子进程期间,来提高负载因子,可以避免在子进程中进行rehash,规避不必要的内存写入,节约内存,另外也是为了尽可能减少内存页过多分离,系统需要更多的开销去回收内存。
  2. 扩容
    1. 扩容操作就是rehash的操作,redis在rehash是占用主线程的,所以采用渐进式rehash(即每次只移动一个链表)。这样避免了客户端的指令堆积与阻塞
    2. 是在重新rehash的时候,ht[0]和ht[1]都有效。在平常,就只有ht[0]生效,而ht[1]是空的
    3. 当rehash完成,则会将0进行释放,将1设置为0,在将1初始化成新的hash表
    4. 在开始和完成rehash,会去更新rehashidx = 0(表示rehash开始工作,每进行一次rehash,rehashidx += 1)和 rehashidx = -1(结束rehash)
  3. 缩容
    1. 负载因子小于0.1
  4. reash时的CURD
    1. 插入。只会在ht[1]上进行新增
    2. 查询,更新与删除:会在ht[0]和ht[1]上同时执行,如果ht[0]上没找到,则会在ht[1]上操作。

注:触发rehash的操作有查询、插入和删除元素。插入与删除很好理解,但是查询又是为什么呢?

其原因就在于当哈希桶中的链表过长时,那么查询性能会显著降低(链表的查找时间复杂度为O(N)),Redis为了避免类似的问题从而会进行Rehash操作

粗略的画了下rehash的流程,详细的可以看redis的rehash,这里讲的是老版本的redis,但是rehash基本没变,所以我给他放上来

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值