zoukankan      html  css  js  c++  java
  • reids (2)链表与字典

    redis 底层数据结构之链表:
    list:{

    listnode *head

    listnode *tail

    unsigned long len 所包含节点数量

    void *(*dup) (void *ptr); 复制当前节点所保存的值

    void (*free)(void *ptr ) 释放节点所占用内存

    int (*match)(void *ptr,void *key) 节点值对比函数

    }

    listnode:{

    listnode  *prev

    listnode *next

    void *value

    }listnode

    特别说明 head 节点的prev指针与tail节点的next指针是一个空值,也就意味着,该链表是无环链表

    字典:

    redis的数据库就是使用字典来作为底层实现的

    redis的字典是使用哈希表来实现的

    而哈希表的结构用dictht定义表示

    dictht{

    // **table 为哈希表数组

     dictentry **table

    //table的大小

    unsigned long size

    // 哈希表大小掩码,用以计算哈希值,总等于size-1

    unsigned long_sizemask

    // 哈希表已有节点数量

    unsigned long used

    }

    table是一个数组,数组中的每一个元素都是指向dictentry的指针,每个dictentry保存着一个键值对

    dictentry{

    void *key

    union {

    void *val;

    uint64_t u64;

    int 64_t s64;

    }v;

    //指向下一个dictentry指针

    struct dictentry *next  (next 属性指向另一个哈希表节点的指针,这个指针可以将多个哈希值相同的键key连接在一起),形成一个链表

    通过对上述两种数据结构的介绍,可以得到redis字典的结构:

    dict:{

    dicttype *type;

    void *privdata;//私有数据

    dictht ht[2] // 哈希表

    int trehashidx //当rehash不在进行时,值为-1

    }dict

    重点介绍type属性,type属性是一个指向dicttype结构的指针,而这个结构保存了了一簇用于操作特定类型键值对的函数,redis会为不同的字典设置不同的类型特定函数

    ht数组每一个项都是一个dictht哈希表,一般情况下,字典使用ht【0】而ht【1】则会在rehash的时候使用

    哈希算法:

    计算键的哈希值,会用到上面提供到的操作特定类型键值对的函数,如hash= dict->type->hasFunction(key)

    index =hash & dict->ht[x].sizemask 而计算出的index就是dictht中的dictentry数组中的索引位置 ,具有相同索引的键会通过dictentry的next连接起来
    rehash:rehash的原因就是因为随着操作的执行,对于哈希表保存的键值对会逐渐增加或者减少,为了让哈希表的负载因子维持在一个合理的范围内,当哈希表保存的键值对数量太多或者太少时

    程序需要对哈希表的代销进行相应的扩展或者收缩

    对于扩展操作,将ht[1]的大小为第一个大于等于ht[0].used*2的2n    

    如果执行的是收缩操作那么h[1]的大小为第一个大于等于h[0].used的2n 

    将h[0]的所有键值对通过rehash(重新计算键的hash值与索引值),将键值对放到ht[1]哈希表的指定位置上,此时ht【0】为空,则释放ht【0】,让ht【1】设置为ht【0】,并创建ht【1】为下一次rehash做准备

    哈希表的扩展时机:
    服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表负载因子>=1

    服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表负载因子>=5

    负载因子计算方式:

    load_factor =ht[0].used/ht[0].size

    负载因子=哈希表中以保存节数量/哈希表大小

    当负载因子<0.1时,程序自动开始对哈希表执行收缩操作

    此时还有一个坑就是当指向BGSAVE 还有BGREWRITEAOF时为何服务器会提高执行扩展操作所需负载因子,从而尽可能地避免在子进程存在期间进行哈希表的扩展操作,这可以避免必要额内存写入操作,最大限度的节约内存。

    更新:明白了这样虽然减少了额外内存,但是也会使hash表键值对分布不会较好的满足离散分布,使得每个dictentry上挂着太多的键值对

    渐进式哈希:为了避免收缩或者扩展需要进行的rehash操作如果键值对过多对于服务器性能的影响,将rehash操作非一次性,集中式地完成,而是分多次,渐进式的完成

    过程如下:在rehash期间,让rehashindex的值为0,每次对字典进行添加,删除,查找,或者更新操作时,程序除了执行指定操作,还会降ht【0】rehashindex索引上的所有键值对rehash到ht【1】

    当每一次的rehash完成时,会让rehashindex的值增加1,最后当rehashidnex的值到达used时,全部rehash完成,重新让rehashindex值变为-1

  • 相关阅读:
    我看到的我未曾是你们看到的我。
    nagios状态数据更新不及时问题
    Ubuntu下安装 nagiosgraph报错处理
    禁止、允许PING
    windows批量关机
    [转载]div仿框架(B/S结构软件界面)详解[非quirks模式全兼容]
    rrdtool错误attempt to put segment in horiz list twice
    命令参考大全 iostat
    SAP学习手册
    顾问成长之路
  • 原文地址:https://www.cnblogs.com/foreverlearnxzw/p/13778046.html
Copyright © 2011-2022 走看看