• redis设计与实现总结--字典


    字典,用于保存键值对的抽象数据结构。
    每个键都是独一无二的。
    Redis的数据库就是使用字典作为底层实现的。
    还是哈希键的底层实现之一,当一个hash键包含的键值对比较多,又或者键值对中的元素都是比较长的字符串时,Redis就用字典作为哈希键的底层实现
     
    哈希表
    typedef struct dictht {
        //哈希表数组
        dictEntry **table;
        //哈希表大小
        unsigned long size;
        //哈希表大小掩码,用于计算索引值
        //总是等于size-1,用hash值&掩码得到
        unsigned long sizemark;
        //该哈希表已有节点的数量
        unsigned long used;
    }dictht;
    哈希表节点
    typedef struct dictEntry {
        //
        void *key;
        //
        union{
            void *val;
            uint64_t u64;
            int64_t s64;
        }v;
        //指向下一个哈希表节点,形成链表
        struct dictEntry *next;
    }dictEntry;
    typedef struct dict {
        //类型特定函数
        dictType *type;
        //私有数据
        void *privdata;
        //哈希表
        dictht ht[2];
        //rehash索引
        //当rehash不在进行时,值为-1
            int trehashidx;
    }dict;
    type属性和privdata属性是针对不同类型的键值对,为创建多态字典而设置的。
     
    字典采用的是MurmurHash2算法进行hash操作。算法优势:即使输入的键是有规律的,算法仍能给出一个很好的随机分布性,并且算法的计算速度也非常快。
    当发生hash冲突时会用开链的方式。
     
    rehash是为了让hash表的负载因子(used/size)维持在一个合理的范围内,对哈希表进行扩展或收缩,此时用到ht[1]。
        如果是扩展操作,则将ht[1]的大小设为第一个大于等于ht[0].used*2的2的ht[0].used*2的2^n
        如果是收缩操作,那么ht[1]的大小应该为第一个大于等于ht[0].used的2^n。
    将ht[0]的键值对重新进行hash操作放入ht[1]中。然后将ht[1]作为ht[0],将ht[1]置空。
     
    当以下条件中任意一个被满足时,程序自动对hash表进行扩展操作:
    1.服务器目前没有执行BGSAVE命令或者BGREWRITEAOF命令,并且hash表的负载因子大于等于1.
    2.服务器正在执行BGSAVE命令或者BGREWRITEAOF命令,并且hash表的负载因子大于等于5.
    为什么要这样,因为在执行这两个命令时,Redis要创建当前服务器的子进程,而大多操作系统采用写时复制的方法优化子进程的使用效率,所以在子进程存在期间,服务器
    会提高负载因子,从而尽可能的避免在子进程存在期间进行hash表的扩展操作,这可以避免不必要的内存写入操作,最大限度节约内存,
     
    当hash表的负载因子小于0.1时会自动进行收缩操作。
     
    渐进式rehash
    用到了rehashidx,而不是一次性的将ht[0]中的所有键值对rehash到ht[1]。也就是将rehshidx不断加一,一行一行将其键值对搞到ht[1].
    这样的好处是,例如此时有个删除操作我就只需要对比reshidx的值,从而判断需不需要在ht[0]里找。这样就能减轻负担,如果没有rehashidx,就要一直找,无法判断是否在ht[0]中。
     
    对于正在rehash时添加操作会直接在ht[1]操作,其他删除,查找,更新,都要在ht[0]找完ht[1]找。
  • 相关阅读:
    mysql uodate 报错 You can't specify target table '**' for update in FROM clause
    设置mysql InnoDB存储引擎下取消自动提交事务
    SQL插入数据--数据中的某一列来自本表中的数据
    服务器部署静态页面
    json 和 jsonp
    Git 回滚
    java 自定义注解
    java BlockingQueque的多种实现
    java 多线程之ReentrantLock与condition
    storm 架构原理
  • 原文地址:https://www.cnblogs.com/2462478392Lee/p/14744995.html
Copyright © 2020-2023  润新知