Redis 学习 ---- 4.字典

4.1 字典的实现

哈希表由dict.h/dictht结构定义:

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

哈希表结点:

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

Redis中的字典由dict.h/dict结构表示:

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

type属性和privdata属性是针对不同类型的键值对,为创建多态字典而设置的:

        ①type属性是一个指向dictType结构的指针,每个dictType结构保存了一簇用于操作特定类型键值对的函数,Redis会为用途不同的字典设置不同的类型特定函数。

        ②而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;


4.2 哈希算法

当字典被用作数据库的底层实现,或者哈希键的底层实现时,Redis使用MurmurHash2算法来计算键的哈希值。


MurmurHash算法最初由Austin Appleby于2008年发现,这种算法的有点在于,即使输入的键是有规律的,算法仍能给出一个很好的随机分布性,并且算法的计算速度也非常快。该算法主页:http://code.google.com/p/smhasher/

4.3 解决键冲突

Redis的哈希表使用链地址法来解决键冲突.


4.4 rehash

扩展和收缩哈希表的工作可以通过执行rehash(重新散列)操作来完成


哈希表的扩展与收缩

当一下条件中的任意一个被满足时,程序会自动开始对哈希表执行扩展操作:

        1)服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载银子大于等于1。

        2)服务器目前正在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载银子大于等于5。

// 负载因子  = 哈希表已保存结点数量 / 哈希表大小
load_factor = ht[0].used / ht[0].size

另一方面,当哈希表的负载因子小于0.1时,成灰自动开始对哈希表执行收缩操作

 

4.5 渐进式rehash

渐进式rehash执行期间,删除,查找,更新等操作会在俩个哈希表上进行。新增保存在ht[1]里


4.7 重点回顾

Ⅰ 字典被广泛用于实现Redis的各种功能,其中包括数据库和哈希键

Ⅱ Redis中的字典使用哈希表作为底层实现,每个字典带有俩个哈希表,一个平时使用,另一个仅在进行rehash时使用

Ⅲ 当字典被用作数据库的底层实现,或者哈希键的底层实现时,Redis使用MurmurHash2算法来计算键的哈希值

Ⅳ 哈希表使用链地址法来解决键冲突,被分配到同一个索引上的多个键值对会联接成一个单向链表

Ⅴ 在对哈希表进行扩展或者收缩操作时,程序需要将现有哈希表包含的所有键值对rehash到新哈希表里面,并且这个rehash过程并不是一次性地完成的,而是渐进式地完成。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值