zoukankan      html  css  js  c++  java
  • 第四章 字典

    在字典中,一个键(key)可以和一个值(value)进行关联(或者说将键映射为值),这些关联的键和值就称为键值对。

    4.1 字典的实现

      Redis的字段使用哈希表作为底层实现。

      4.1.1 哈希表

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

      table是一个数组,其中每个元素是指向一个哈希表节点的指针。

      size记录了table的大小。sizemask和哈希值一起决定一个键应该被放到table数组的哪个索引上。

      4.1.2 哈希表节点

      每个dictEntry结构保存着一个键值对。其中值可以是一个指针,或者uint64_t整数,或者int64_t整数。next属性指向另一个哈希表节点的指针,这个指针可以将多个哈希值相同的键值对连接在一起,解决哈希冲突的问题。

    typedef struct dictEntry{
        //
        void *key;
        
        //
        union{
            void *val;
            uint64_t u64;
            int64_t s64;
        }v;
     
        //指向下一个哈希表节点,形成链表
        struct dictEntry *next;
    
    }dictEntry;

      4.1.3 字典

      Redis中的字典结构:

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

      type和privdata是为了多态字典而设计的,其中type指向了一个dictType结构,里面定一个了一系列操作键值对的函数,而privdata存放了函数需要的入参。

    typedef struct dictType{
        //计算哈希值的函数
        unsigned int (*hashFunction)(const void *key);
    
        //复制键的函数
        void *(*keyDup)(void *privdata, const void *key);
    
        //复制值的函数
        void *(*valDup)(void *privdata, const void *obj);
    
        //对比键的函数
       int (*keyCompare)(void *privdata, const void *key1, const void *key2);
      
        //销毁键的函数
        void (*keyDestructor)(void *privdata, void *key);
    
        //销毁值的函数
        void (*valDestructor)(void *privdata, void *obj);
    }dictType;

      ht属性是一个包含两个项的数组,数组中的每个项都是一个dictht哈希表,一般情况下,字典只使用ht[0]哈希表,ht[1]哈希表只会在rehash时使用,rehashidx记录了rehash的进度。

    4.2 哈希算法

      先计算key的哈希值,根据哈希值和sizemask计算索引值。根据索引值将键存放到指定位置。

    4.3 解决键冲突

      当有两个及以上的键被分到同一个索引上时,产生了哈希冲突,Redis的解决方法是链地址法,将冲突的部分排成链表。因为没有指向链表表尾的指针,出于速度考虑,最新插入的放在表头位置。

    4.4 rehash

    1. 为ht[1]分配空间
      1. 如果是扩展操作,取第一个大于等于ht[0].used*2的2的n次方幂
      2. 如果是收缩操作,取第一个大于等于ht[0].used的2的n次方幂
    2. 将ht[0]中的键值对重新映射到ht[1]中
    3. 将ht[0]空间释放,将ht[1]设置为h[0],将ht[0]设置为ht[1],并在ht[1]处创建一个新的空白哈希表,为下次rehash做准备

    4.5 渐进式rehash

      渐进是指当键值对太多的情况,并不会一次全部重新分配完。

    1. 为ht[1]分配空间,字典同是持有ht[0]和ht[1]两个哈希表
    2. 将rehashidx初始化为0
    3. 每次对字典执行增删改查操作时,程序还会额外将ht[0]表在rehashidx索引上所有的键值对rehash到ht[1]中,当操作完毕时,将rehashidx+1
    4. 最终,ht[0]的所有键值对全部迁移完,将rehashidx重置为-1

      在渐进rehash期间,新增的键值对,一律保存在ht[1]中。删改查则先在ht[0]中查找,未找到再去ht[1]中查找。

    人生就像蒲公英,看似自由,其实身不由己。
  • 相关阅读:
    HDU 1358 Period (KMP)
    POJ 1042 Gone Fishing
    Csharp,Javascript 获取显示器的大小的几种方式
    css text 自动换行的实现方法 Internet Explorer,Firefox,Opera,Safar
    Dynamic Fonts动态设置字体大小存入Cookie
    CSS Image Rollovers翻转效果Image Sprites图片精灵
    CSS three column layout
    css 自定义字体 Internet Explorer,Firefox,Opera,Safari
    颜色选择器 Color Picker,Internet Explorer,Firefox,Opera,Safar
    CSS TextShadow in Safari, Opera, Firefox and more
  • 原文地址:https://www.cnblogs.com/walker993/p/14425825.html
Copyright © 2011-2022 走看看